一、概述
本文將推出一個新的進程注入技術,我們稱之為“Ctrl-Inject”,它利用了控制臺應用程序中處理Ctrl信號的機制。作為研究的一部分,在瀏覽MSDN時,我們看到了關于Ctrl信號處理的以下評論:“與SetConsoleCtrlHandler函數一起使用的應用程序定義函數??刂婆_進程使用此功能來處理進程收到的控制信號。當收到信號時,系統會在過程中創建一個新線程來執行該功能?!?/p>
這意味著每觸發一個信號到一個基于控制臺的進程時,系統就會在一個新線程中調用處理函數??吹竭@一點,我們認為可以利用此功能執行一個不同的進程注入。
二、控制信號處理
每當用戶(或進程)向基于控制臺的進程(如cmd.exe或powershell.exe)發送Ctrl+C(或Break)信號時,系統進程csrss.exe就會在目標進程中調用新的函數CtrlRoutine 。
CtrlRoutine函數負責包裝使用SetConsoleCtrlHandler設置的hander。深入探究CtrlRoutine,我們注意到下面的一段代碼:
圖1:在運行和CFG檢查之前解碼指針
該函數使用名為HandlerList的全局變量來存儲回調函數列表,在該函數中迭代它,直到其中一個hander返回TRUE通知該信號已被處理。
為了使hander成功執行,它必須滿足以下條件:
· 函數指針必須正確編碼——hander列表中的每個指針都使用RtlEncodePointer進行編碼,并在執行之前使用RtlDecodePointer API進行解碼。因此,未編碼的指針很容易使程序崩潰。
· 指向有效的CFG(控制流防護)目標。 CFG通過驗證間接調用的目標是否為有效函數來保護間接調用。
我們來看一下SetConsoleCtrlHandle ,看看它如何設置一個Ctrl hander,以便稍后可以復制。在圖2中,可以看到每個指針在添加到HandlerList之前是如何編碼的。
圖2:在保存之前對指針進行編碼
繼續,我們看到一個名為SetCtrlHandler的內部函數的調用。這個函數更新了兩個變量,HandlerList為它添加一個新的指針,另一個全局變量叫做HandlerListLength,增加了它的長度以適應新的列表大小。
圖3:更新HandlerList并增加HandlerListLength
由于HandlerList和HandlerListLength變量駐留在kernelbase.dll模塊中,并且由于此模塊映射到所有進程的相同地址,所以可以在我們的進程中找到它們的地址,然后使用WriteProcessMemory在遠程進程中更新它們的值。我們的工作還沒有完成,因為CFG和指針編碼已經到位,我們需要找到一種方法來繞過它們。
三、繞過指針編碼
在Windows 10之前,需要了解指針編碼/解碼如何工作以避開指針編碼保護。那么,讓我們來深入了解EncodePointer的工作原理。
圖4:RtlEncodePointer的內部工作原理
最初,有一個對NtQueryInformationProcess的調用。讓我們來看看它的定義:
NTSTATUS WINAPI NtQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
根據定義,可以做出以下假設:
· ProcessHandle: 當傳遞值-1時,它告訴函數我們要調用進程。
· ProcessInformationClass: 此參數的值為0x24,這是一個未公開的值,要求內核獲取進程secretcookie。cookie本身駐留在EPROCESS結構中。
在獲取secretcookie后,我們可以看到幾個涉及輸入指針和secretcookie的操作。這與以下等式等價:
EncodedPointer = (OriginalPointer ^ SecretCookie) >> (SecretCookie & 0x1F)
繞過此方法的一種方式是使用CreateRemoteThread 執行RtlEncodePointer 并將NULL作為參數傳遞給它,如下所示:
1) EncodedPointer = (0 ^ SecretCookie) >> (SecretCookie & 0x1F)
2) EncodedPointer = SecretCookie >> (SecretCookie & 0x1F)
可以看出,cookie循環31次(在Windows 10 此64比特值為63,0x3f)得到返回值。如果我們在目標進程上使用已知的編碼地址,我們將能夠暴力破解原始cookie值。下述代碼演示了如何對cookie執行這種暴力攻擊:
自Windows 10以來,微軟非??犊靥峁┝艘唤M新的API,稱為:RtlEncodeRemotePointer 和RtlDecodeRemotePointer。
顧名思義,傳遞一個進程句柄和指針,它將為目標進程返回一個有效的編碼指針。
另一種值得提及的提取cookie的技術可以在這里找到:here。
四、繞過控制流監控(CFG)
到目前為止,我們已經將代碼注入到了目標進程中,并修正了HandlerList和HandlerListLength的值。如果嘗試通過發送CTRL + C信號來觸發我們的代碼,該進程將引發異常并自行終止。這是因為CFG會注意到我們正在嘗試跳轉到一個不是有效調用目標的指針。
幸運的是,微軟一直對我們非常友善,通過發布另一個有用的API,名為SetProcessValidCallTargets。
WINAPI SetProcessValidCallTargets(
_In_ HANDLE hProcess,
_In_ PVOID VirtualAddress,
_In_ SIZE_T RegionSize,
_In_ ULONG NumberOfOffsets,
_Inout_ PCFG_CALL_TARGET_INFO OffsetInformation
?。?
簡而言之,傳遞進程句柄和指針,它就將其設置為有效的調用目標。使用我們在之前的博文(previous blog posts)中介紹的未記錄在案的API也可以做到這一點。
五、觸發CTRL-C事件
現在一切就緒,所需要做的就是在目標進程上觸發Ctrl + C以調用我們的代碼。有幾種方法可以觸發它。在這里,我們使用SendInput的組合來觸發系統范圍的Ctrl鍵按鍵,以及用于發送C鍵的PostMessage。這也適用于隱藏/不可見的控制臺窗口。下面是觸發Ctrl-C信號的函數:
六、幕后
實際上,在這個進程注入技術中,我們將代碼注入到目標進程中,但是我們并沒有直接調用它,也就是說,我們從來沒有使用SetThreadContext調用CreateRemoteThread或更改執行流。相反,我們正在使csrss.exe為我們調用它,因為這是一種正常的行為。
這是因為每次將Ctrl + C信號發送到基于控制臺的應用程序時,conhost.exe會調用類似于以下調用堆棧的內容,如下所示。
其中CsrClientCallServer返回一個唯一索引標識符(0x30401),然后將其傳遞給csrss.exe服務器。
從那里調度表中調用一個名為SrvEndTask的函數。下圖說明調用堆棧:
在這個調用鏈的最后,終于看到了RtlCreateUserThread,它負責在目標進程上執行我們的線程。
注: 雖然Ctrl-Inject技術僅限于控制臺應用程序,但有很多控制臺應用程序可能會被濫用,最值得注意的是cmd.exe。
七、總結
現在我們已經了解了這個進程注入在實踐中是如何工作的以及幕后發生了什么,來總結一下Ctrl-Inject技術。與傳統線程注入技術相比,這種技術的主要優點是遠程線程由可信的Windows進程csrss.exe創建,這使得它更加隱身。缺點是它僅限于控制臺應用程序。
執行這種進程注入技術所需的步驟如下:
1. 使用OpenProcess打開控制臺進程。
2. 調用VirtualAllocEx為惡意payload分配一個新的緩沖區。
3. 使用WriteProcessMemory將數據寫入分配的緩沖區。
4. 使用目標進程cookie將指針指向緩沖區。通過調用帶有空指針的RtlEncodePointer并手動編碼指針或通過調用RtlEncodeRemotePointer來實現。
5. 使用SetProcessValidCallTargets讓遠程進程知道新指針是有效指針。
6. 最后,使用PostMessage和SendInput的組合觸發Ctrl+C信號。
7. 恢復原始處理程序列表。
1024你懂的国产日韩欧美_亚洲欧美色一区二区三区_久久五月丁香合缴情网_99爱之精品网站
責任編輯:韓希宇
免責聲明:
中國電子銀行網發布的專欄、投稿以及征文相關文章,其文字、圖片、視頻均來源于作者投稿或轉載自相關作品方;如涉及未經許可使用作品的問題,請您優先聯系我們(聯系郵箱:cebnet@cfca.com.cn,電話:400-880-9888),我們會第一時間核實,謝謝配合。