程序正在進行遠程線程注入 遠程進程注入



文章插圖
程序正在進行遠程線程注入 遠程進程注入

文章插圖
譯者:myswsun
預估稿費:300RMB
投稿方式:發送郵件至linwei## , 或登陸網頁版在線投稿
0x00 前言
進程注入是一種廣泛應用于惡意軟件和無文件攻擊中的逃避技術 , 這意味著可以將自定義代碼運行在另一個進程的地址空間內 。進程注入提高了隱蔽性 , 也實現了持久化 。盡管有非常多的進程注入技術 , 但是本文我只列舉了10種常見的技術 。我還提供了這些技術的相關截圖以便逆向和惡意軟件的分析 , 并幫助防御這些技術 。
0x01 通過CreateRemoteThread和LoadLibrary的DLL注入
這是進程注入最常見的技術 。惡意軟件將惡意的動態鏈接庫的路徑寫入另一個進程的虛擬地址空間內 , 通過在目標進程中創建遠程線程來確保遠程進程加載它 。
惡意軟件首先需要選擇目標進程(例如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)的惡意軟件使用了這種技術 。
0x02 可執行文件注入(PE注入)
惡意軟件并不傳入LoadLibrary的地址 , 而是拷貝惡意代碼到打開的進程中并執行(通過小段shellcode或者調用CreateRemoteThread) 。與LoadLibrary相比 , PE注入的優勢是惡意軟件不需要在磁盤中釋放一個惡意的DLL 。與上個技術類似 , 惡意軟件在目標進程中分配內存 , 調用WriteProcessMemory將惡意代碼而不是DLL路徑寫入內存 。然而 , 這種方式的缺陷是被復制的映像的基址的改變 。當一個惡意軟件注入PE到另一個進程 , 它的新基址是不可預料的 , 需要動態重新計算PE的地址 。為了完成這個 , 惡意軟件需要找到目標進程的重定位表 , 并根據它的重定位描述解析被復制映像的絕對地址 。
這種技術和其他技術很類似 , 如反射DLL注入和內存模塊加載 , 因為他們都不釋放任何文件到磁盤 。但是 , 內存模塊和反射DLL注入更加隱蔽 。他們不依賴Windows API(如CreateRemoteThread或LoadLibrary) , 因為他們在內存中加載并執行自身 。反射DLL注入通過在內存中創建一個DLL映射執行 , 而不依賴Windows的加載器 。內存模塊加載和反射DLL注入類似 , 其不同之處只是在于內存模塊加載的注入器或加載器負責映射目標DLL到內存中而不是DLL自身映射 。在之前的博文中 , 討論過這兩種技術 。
當分析PE注入時 , 在調用CreateRemoteThread之前通常能看見循環(通常是兩個for循環 , 一個嵌套在另一個中) 。這種技術在crypter(加密和混淆軟件)中非常流行 。下圖中的樣本(Sha256:ce8d7590182db2e51372a4a04d6a0927a65b2640739f9ec01cfd6c143b1110da)充分利用了這種技術 。在調用WriteProcessMemory和CreateRemoteThread之前有兩層循環來處理重定位 ?!癮nd 0x0fff”指令也是一個比較好的表征 , 它標明了頭12位用于得到包含重定位塊的虛擬地址的偏移量 ?,F在惡意軟件重新計算了所有需要的地址了 , 只需要將起始地址傳入CreateRemoteThread并執行就行了 。
0x03 進程hollow(又名進程替換和RunPE)
惡意軟件有一種技術叫進程hollow , 而不是注入代碼到程序中(如DLL注入) 。進程hollow發生在惡意軟件unmap目標進程的合法內存代碼 , 并使用惡意的代碼覆寫目標進程的內存(如svchost.exe)的時候 。
惡意軟件首先以掛起模式創建一個新進程來容納惡意代碼 。如下圖(Sha256:eae72d803bf67df22526f50fc7ab84d838efb2865c27aef1a61592b1c520d144) , 以CREATE_SUSPENDED (0x00000004)為參數調用CreateProcess 。新進程的主線程創建后就處于掛起狀態 , 直到調用ResumeThread才會繼續執行 。接下來 , 惡意軟件需要使用惡意的payload來填充合法文件的內容 。調用ZwUnmapViewOfSection或者NtUnmapViewOfSection來unmap目標進程的內存 。這兩個API將釋放section指向的所有內存 。內存unmap之后 , 使用WriteProcessMemory將惡意軟件的節寫入目標進程 。調用SetThreadContext將入口點指向它已寫入的新的代碼節 。最后 , 調用ResumeThread恢復掛起進程的執行 。
0x04 線程執行劫持(又名掛起、注入并恢復)
這種技術類似于進程hollow 。在線程執行劫持中 , 惡意軟件的目標是進程中已存在的線程 , 而且沒有創建任何進程或線程 。因此 , 在分析期間你可能看見CreateToolhelp32Snapshot和Thread32First、OpenThread 。
在得到目標線程的句柄后 , 惡意軟件調用SuspendThread將線程掛起 。調用VirtualAllocEx和WriteProcessMemory來分配內存并執行代碼注入 。代碼包含shellcode , 惡意DLL的路徑和LoadLibrary的地址 。
下圖(Sha256:787cbc8a6d1bc58ea169e51e1ad029a637f22560660cc129ab8a099a745bd50e)描述了一個普通木馬是如何使用這種技術的 。為了劫持線程的執行 , 惡意軟件調用SetThreadContext修改目標線程的EIP寄存器(包含下條執行指令的地址的寄存器) 。隨后 , 惡意軟件恢復線程繼續執行它已寫入到宿主進程的shellcode 。從攻擊者的角度看 , 這種方式是有問題的 , 因為在系統調用的中途掛起并恢復線程可能引起系統崩潰 。為了避免這種情況的發生 , 更復雜的利用技術是 , 一旦EIP寄存器在NTDLL.dll中就恢復并重試 。
0x05 通過SetWindowsHookEx鉤子注入
鉤子是用于攔截函數調用的一種技術 。惡意軟件能利用指定線程中事件觸發來加載他們的惡意DLL 。通常使用SetWindowsHookEx來安裝消息鉤子 。SetWindowsHookEx有4個參數 。第一個參數是事件的類型 。事件有很多的類型 , 有鍵盤按鍵(WH_KEYBOARD)和鼠標輸入(WH_MOUSE)等 。第二個參數是個函數指針 , 指向惡意軟件想要處理事件的函數 。第3個參數是包含函數的模塊 。因此 , 通??梢钥匆奓oadLibrary、GetProcAddress、SetWindowsHookEx 。最后一個參數是消息鉤子關聯的線程 。如果值為0 , 則針對所有線程 。然而 , 只針對某個線程的目標會小很多 , 因此也可能看見CreateToolhelp32Snapshot和Thread32Next 。一旦DLL被注入后 , 惡意軟件將執行惡意代碼 。下圖中 , 勒索軟件Locky(Sha256:5d6ddb8458ee5ab99f3e7d9a21490ff4e5bc9808e18b9e20b6dc2c5b27927ba1)就使用了這種技術 。
0x06 通過注冊表修改(如AppInit_DLLs , AppCertDlls , IFEO)
Appinit_DLL, AppCertDlls, IFEO(映像劫持)可以用于注入和持久化 。完整的路徑如下:
AppInit_DLLs
惡意軟件能在AppInit_DLLs鍵下插入惡意的DLL的路徑 , 以便其他進程加載 。該鍵下每個DLL會被加載到所有的加載User32.dll的進程中 。User32.dll是常見的Windows基礎庫 。因此 , 當惡意軟件修改這個子鍵時 , 大量進程將加載惡意的DLL 。下圖中 , 木馬Ginwui(Sha256:9f10ec2786a10971eddc919a5e87a927c652e1655ddbbae72d376856d30fa27c)依賴了這種技術 。它通過調用RegCreateKeyEx打開AppInit_DLLs鍵 , 并調用RegSetValueEx修改它 。
AppCertDlls
這種方式類似與AppInit_DLLs , 除了該鍵下的DLL會加載到調用Win32 API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW, WinExec的進程中 。
IFEO
IFEO通常用于調試 。開發者能在該鍵下設置調試器 , 來附加調試 。因此 , 當可執行文件啟動時 , 附加到它的程序也會啟動 。為了使用這功能 , 你能簡單的設置調試器的路徑 , 并附加到你想分析的可執行文件上 。下圖 , 木馬Diztakun(Sha256:f0089056fc6a314713077273c5910f878813fa750f801dfca4ae7e9d7578a148)使用了這種技術 , 它修改了任務管理器的調試器的值 。
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表來寫入到另一個進程的內存 。
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)的惡意軟件使用了這種技術 。
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分析的結果 。
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 。
0x0B 總結
本文中 , 我描述了惡意軟件用于隱藏自身行為的10種不同的技術 。通常 , 惡意軟件直接注入shellcode到另一個進程中或者強制其他進程加載惡意DLL 。如下表 , 我已經將不同的技術進行了分類 , 并提供了樣本 , 用于查看在本文提到的每個注入技術 。這可以幫助研究者用于在逆向時識別各種技術 。
【程序正在進行遠程線程注入 遠程進程注入】攻擊者和研究員一直在研究新的注入和隱蔽的技術 。本文介紹了10種常見的技術 , 但是還有其他的 , 如COM劫持 。防御者任重道遠 。