公司有個(gè)監(jiān)控程序涉及到進(jìn)程的保護(hù)問(wèn)題,需要避免用戶通過(guò)任務(wù)管理器結(jié)束掉監(jiān)控進(jìn)程,這里使用了HOOK技術(shù),通過(guò)Hook OperProcess來(lái)實(shí)現(xiàn)進(jìn)程的保護(hù). 正常的結(jié)束進(jìn)程的流程是(應(yīng)用層) a.OpenProcess 打開進(jìn)程,獲取進(jìn)程的句柄. b.將a獲取的進(jìn)程句柄傳遞給TerminateProcess,最后由TermianteProcess來(lái)完成進(jìn)程的關(guān)閉. ps:TerminateProcess又會(huì)調(diào)用系統(tǒng)的NtTerminateProcess,然后逐步深入內(nèi)核層,最終調(diào)用內(nèi)核API完成進(jìn)程的關(guān)閉和進(jìn)程相關(guān)資源的釋放. (在應(yīng)用層大多數(shù)進(jìn)程的關(guān)閉都是走上面流程的,包括任務(wù)管理器,所以我們知道在Opernprocess和TerminateProcess間,我們只要Hook OpenProcess,讓程序無(wú)法打開進(jìn)程獲取到句柄就可以了,那樣TerminateProcess調(diào)用自然也就失敗了) HANDLE WINAPI OpenProcess( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwProcessId //進(jìn)程ID,我們所關(guān)注的 ); 由OpenProcess函數(shù)原型我們知道,第三個(gè)參數(shù)dwProcessId標(biāo)識(shí)要打開進(jìn)程的ID,而我們可以通過(guò)攔截OpenProcess,然后判斷dwProcess是否為保護(hù)的進(jìn)程ID. 例如:我們自定義的Hook_OpenProcess HANDLE WINAPI Hook_OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId) { //判斷打開進(jìn)程的權(quán)限和PID,其中l(wèi)pData->dwProcessId存儲(chǔ)我們要保護(hù)的進(jìn)程ID if(dwDesiredAccess == PROCESS_TERMINATE && dwProcessId == lpData->dwProcessId) { //為保護(hù)的進(jìn)程直接返回NULL給TerminateProcess return NULL; } return OpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId); } 定制好了自己的OpenProcess的函數(shù),接下來(lái)我們要做的就是如何將原函數(shù)(OpenProcess)替換為我們自己的Hook_OpenProcess,只有程序在調(diào)用OpenProcess時(shí)候先走我們的Hook_OpenProcess那么保護(hù)才能順序的進(jìn)行. 而替換的主要方法主要有: 1. 通過(guò)Patch IAT表,要求對(duì)PE文件格式熟悉 2. 通過(guò)修改原函數(shù)的入口處幾個(gè)字節(jié),實(shí)現(xiàn)跳轉(zhuǎn)到我們定制的函數(shù),這種技術(shù)我們稱為inline hook,主要是通過(guò)修改入口前5個(gè)字節(jié)或者7個(gè)字節(jié),或者patch函數(shù)的中部代碼,也可以patch尾部. 我們這里用的是第一種方法,這里HOOK類,使用的《核心編程》中的CAPIHook,例如: class QHookSrv { public: // Hook a function in all modules QHookSrv(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook, BOOL fExcludeAPIHookMod); // Unhook a function from all modules ~QHookSrv(); // Returns the original address of the hooked function operator PROC() { return(m_pfnOrig); } private: static PVOID sm_pvMaxAppAddr; // Maximum private memory address static QHookSrv* sm_pHead; // Address of first object QHookSrv* m_pNext; // Address of next object PCSTR m_pszCalleeModName; // Module containing the function (ANSI) PCSTR m_pszFuncName; // Function name in callee (ANSI) PROC m_pfnOrig; // Original function address in callee PROC m_pfnHook; // Hook function address BOOL m_fExcludeAPIHookMod; // Hook module w/CAPIHook implementation? private: // Replaces a symbol's address in a module's import section static void WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName, PROC pfnOrig, PROC pfnHook, BOOL fExcludeAPIHookMod); // Replaces a symbol's address in all module's import sections static void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnOrig, PROC pfnHook, HMODULE hmodCaller); }; QHookSrv實(shí)現(xiàn)代碼: ![]() 掛鉤OpenProcess : //Hook_OpenProcess為定制的攔截函數(shù) QHookSrv g_OpenProcess("kernel32.dll", "OpenProcess",(PROC)Hook_OpenProcess,TRUE); 有了IAT hook類,也有了攔截函數(shù),接下來(lái)我們要做的就是如何patch所有的進(jìn)程中duiOpenProcess的調(diào)用了,這里我們通過(guò)安裝全局的WH_SHELL鉤子來(lái)實(shí)現(xiàn) 應(yīng)用層消息鉤子安裝通過(guò)API: HHOOK WINAPI SetWindowsHookEx( _In_ int idHook, //鉤子的類型(消息鉤子) _In_ HOOKPROC lpfn, //鉤子回調(diào),當(dāng)前響應(yīng)消息被觸發(fā)時(shí)候調(diào)用 _In_ HINSTANCE hMod, //實(shí)例模塊句柄,一般是DLL句柄 _In_ DWORD dwThreadId //0標(biāo)識(shí)全局鉤子,非0標(biāo)識(shí)局部鉤子 ); 消息鉤子的卸載: //只有一個(gè)參數(shù),通過(guò)SetWindowsHookEx返回的鉤子句柄 BOOL WINAPI UnhookWindowsHookEx( _In_ HHOOK hhk ); : 本Demo中鉤子的安裝和卸載過(guò)程 //安裝鉤子 ,由Dll導(dǎo)出 //參數(shù)pid標(biāo)識(shí)保護(hù)進(jìn)程的ID BOOL InstallHook(DWORD pid) { BOOL bResult=FALSE; if(!glhHook) { glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,glhInstance, 0); if(glhHook!=NULL) { //??????湲?? hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,"PCMONITOR."); if(hMapping != NULL) { lpData=(LPSHWP_STRUCT)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0); lpData->dwProcessId = pid; } bResult=TRUE; } } return bResult; } //卸載鉤子,UninstallHook由Dll導(dǎo)出 BOOL UninstallHook() { BOOL bResult=FALSE; if(glhHook) { bResult= UnhookWindowsHookEx(glhHook); if(bResult) { glhHook=NULL; } } return bResult; } 消息回調(diào)函數(shù),回調(diào)不進(jìn)行任何操作調(diào)用CallNextHookEx將消息傳遞下一個(gè)處理程序 static LRESULT WINAPI ShellHookProc(int code, WPARAM wParam, LPARAM lParam) { return ::CallNextHookEx(glhHook, code, wParam, lParam); } + NET(C#)中的調(diào)用: // QomoHookSrv.dll [DllImport("QomoHookSrv.dll", CallingConvention=CallingConvention.Cdecl)] private extern static bool InstallHook( int processID); [DllImport("QomoHookSrv.dll", CallingConvention=CallingConvention.Cdecl)] private extern static bool UninstallHook(); private void install_hook_when_app_startup() { //獲取進(jìn)程的ID int pid = System.Diagnostics.Process.GetCurrentProcess().Id; //安裝鉤子 InstallHook(pid); } private void uninstall_hook_when_app_closed() { UninstallHook(); } 源碼僅包含HOOK DLL代碼(核心代碼), 測(cè)試工程請(qǐng)自行code,文章也已經(jīng)提及了,相對(duì)簡(jiǎn)單
【進(jìn)程保護(hù)知識(shí)擴(kuò)展】 本文中提及是從應(yīng)用層的角度來(lái)保護(hù)進(jìn)程不被關(guān)閉,通過(guò)Hook OperProcess 和TerminateProcess并不是安全了,應(yīng)用程進(jìn)程的關(guān)閉有些不是走該流程的,比如說(shuō)直接調(diào)用NtTerminateProcess或者通過(guò)NtSetSystemInformation等 進(jìn)程關(guān)閉的流程大致為(系統(tǒng)API間的調(diào)用關(guān)系);
通過(guò)上述流程相應(yīng)的進(jìn)程保護(hù)方法: 1.應(yīng)用層Hook OpenProcess/TerminateProcess ,或者調(diào)用RtlSetprocessiscritical 2.內(nèi)核層方式實(shí)現(xiàn)進(jìn)程保護(hù)相對(duì)方式比較多點(diǎn): a. Hook NtTerminaterProcess/ZwTerminateProcess(兩個(gè)是一樣的,在R3是為NtTerminateProcess,內(nèi)核就有NtTerminateProcess轉(zhuǎn)為ZwTerminateProcess調(diào)用),這種攔截可以通過(guò)修改內(nèi)核表SSDT,或者InlineHook實(shí)現(xiàn) b.Hook ObReferenceObjectByHandle ,網(wǎng)上有很多關(guān)于該API的HoOK源碼,也是進(jìn)程保護(hù)中常用的一種手段,因?yàn)楹罄m(xù)的很多操作都是需要通過(guò)調(diào)用該函數(shù)返回的進(jìn)程對(duì)象體 c. Hook PspTerminateThreadByPointer/PspTerminateProcess/PspExitThread ,pspXX函數(shù)是比較底層的API了,而未導(dǎo)出,獲取他們地址需要通過(guò)硬編碼的方式,所以不同的系統(tǒng)可能存在問(wèn)題,所以這種方法是相對(duì)比較危險(xiǎn)的,但是確實(shí)很有效的 d. Hook 插APC函數(shù),例如:KeInitializeApc等這種方法也相對(duì)比較實(shí)用多,網(wǎng)上也有很多這方面的例子,不過(guò)大多數(shù)都是通過(guò)插APC的方式來(lái)強(qiáng)制結(jié)束進(jìn)程的.
專注于: Net分布式技術(shù),移動(dòng)服務(wù)端架構(gòu)及系統(tǒng)安全學(xué)習(xí)及研究 by Andy
|
|