日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

进程隐藏与进程保护(SSDT Hook 实现)(二)

發(fā)布時(shí)間:2024/4/11 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程隐藏与进程保护(SSDT Hook 实现)(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


文章目錄:

?????????????????

1. 引子 – Demo 實(shí)現(xiàn)效果:

2. 進(jìn)程隱藏與進(jìn)程保護(hù)概念:

3. SSDT Hook 框架搭建:

4. Ring0 實(shí)現(xiàn)進(jìn)程隱藏:

5. Ring0 實(shí)現(xiàn)進(jìn)程保護(hù):

6. 隱藏進(jìn)程列表和保護(hù)進(jìn)程列表的維護(hù):

7. 小結(jié):

????????????????

1. 引子 – Demo 實(shí)現(xiàn)效果:

????????????????????????

上一篇《進(jìn)程隱藏與進(jìn)程保護(hù)(SSDT Hook 實(shí)現(xiàn))(一)》呢把 SSDT 說(shuō)得差不多了,

博文地址:

http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html

不過(guò)呢,那也只是些理論的東西,看不到什么實(shí)物,估計(jì)說(shuō)來(lái)說(shuō)去把人說(shuō)暈了后,也沒(méi)什么感覺(jué),

而這一篇博文的話,給出點(diǎn)新意的,讓人頭腦清醒點(diǎn)的 ~ 所以先給個(gè) Demo 出來(lái)吧 ~

?????

(不好意思,本著不喝倒怎出得了好文章這個(gè)理由,所以今天又喝多了點(diǎn),文章有疏忽之處還請(qǐng)見(jiàn)諒 ~

順便在這里跟朋友們分享一下哈,晚上于這個(gè)時(shí)間點(diǎn),比如 2 點(diǎn)的時(shí)候啊,喝點(diǎn)小酒,

聽(tīng)點(diǎn)曲子,你會(huì)精神振奮,頭腦更加清醒,思路也會(huì)很清晰,尤其是寫起程序來(lái)那是唰唰的來(lái)の ~ )

??????

進(jìn)程隱藏效果:

應(yīng)用程序主界面:

???????????????

隱藏進(jìn)程 taskmgr.exe:

??????????????

取消進(jìn)程隱藏 taskmgr.exe:

????????????????

進(jìn)程保護(hù)效果:

進(jìn)程保護(hù)(保護(hù)自身進(jìn)程 SSDTProcess.exe):

?????????

取消進(jìn)程保護(hù)(這里還是以 SSDTProcess.exe 為例):

下面的截圖表示 SSDTProcess.exe 已經(jīng)被取消了保護(hù),

此時(shí)再到任務(wù)管理器中結(jié)束 SSDTProcess.exe 時(shí),你可以發(fā)現(xiàn)是可以正常結(jié)束這個(gè)進(jìn)程的 ~

????????????

????????????????

2. 進(jìn)程隱藏與進(jìn)程保護(hù)概念:

????????????????????????

在 Ring3 下獲取到當(dāng)前 Windows 操作系統(tǒng)下的所有的進(jìn)程無(wú)外乎以下的幾種方法:

第一種:使用 ToolHelp 遍歷獲取到所有進(jìn)程,關(guān)于這種方式的話,筆者以前寫過(guò)一篇博文的,

《列舉 Windows 所有進(jìn)程(ToolHelp)》博文地址如下:

http://www.cnblogs.com/BoyXiao/archive/2011/02/27/1966383.html

第二種:使用 PSAPI 下的 EnumProcesses 獲取到所有進(jìn)程的 PID,然后提升進(jìn)程權(quán)限為 SE_DEBUG 權(quán)限,

再調(diào)用 OpenProcess 即可打開(kāi)進(jìn)程,從而獲取到進(jìn)程的基本信息(可以查看 MSDN 的 PSAPI 專題)。

第三種:使用未公開(kāi)的本地 API 即位于 Ntdll.dll 中的未文檔化的 API – NtQuerySystemInformation,

而 Windows 任務(wù)管理器就是通過(guò)這種方式來(lái)獲取到所有的進(jìn)程信息的 ~

而事實(shí)上的是,ToolHelp 和 PSAPI 只不過(guò)是對(duì) Ntdll.dll 中 NtQuerySystemInformation API 的一個(gè)封裝,

所以在 Ring3 下獲取系統(tǒng)中所有進(jìn)程信息最終都會(huì)回到 Ndll.dll 中 NtQuerySystemInformation API 的調(diào)用上。

如果要實(shí)現(xiàn)在 Ring3 中對(duì)進(jìn)程進(jìn)行隱藏的話,只需要 Hook 掉 NtQuerySystemInformation API 即可。

???????????????

而至于進(jìn)程保護(hù)的話,我們需要考慮到兩種情況,第一種則是該進(jìn)程自行終止,第二種情況則是該進(jìn)程被其他進(jìn)程給殺掉,

第一種情況基本上對(duì)于窗口應(yīng)用程序來(lái)說(shuō),一般都是用戶點(diǎn)擊了右上角的 x 按鈕,然后產(chǎn)生 WM_CLOSE 消息,

最后由窗口過(guò)程退出進(jìn)程,這種情況下,我們應(yīng)該是需要允許退出的,也就是進(jìn)程是可以正常退出的。

而第二種情況的話,就是進(jìn)程被別的進(jìn)程殺掉,比如在任務(wù)管理器中就可以殺掉絕大部分的應(yīng)用程序進(jìn)程,

而這里的進(jìn)程保護(hù)就是要實(shí)現(xiàn)進(jìn)程不能夠被任務(wù)管理器或者其他的進(jìn)程管理工具殺掉。

在 Ring3 中,由一個(gè)進(jìn)程結(jié)束其他進(jìn)程,調(diào)用的 API 為 Kernel32.dll 中的 TerminateProcess,

如果追溯這個(gè) TerminateProcess,可以發(fā)現(xiàn),其調(diào)用了 Ntdll.dll 中的 NtTerminateProcess API,

然后再追溯下去就可以到 ntoskrnl.exe 中的 ZwTerminateProcess 和系統(tǒng)服務(wù) NtTerminateProcess 了。

而這和我的上一篇博文中介紹 NtQuerySystemInformation 就是一致的了,

所以如果我們要實(shí)現(xiàn)進(jìn)程保護(hù),需要 Hook 的系統(tǒng)服務(wù)就是 NtTerminateProcess ~

????????????????

???????????????

3. SSDT Hook 框架搭建:

????????????????????????

從上面的介紹中,我們可以知道,要想實(shí)現(xiàn)進(jìn)程隱藏和進(jìn)程保護(hù),我們需要在 SSDT 中 Hook 兩個(gè)系統(tǒng)服務(wù),

即 Ring0 下的 NtQuerySystemInformation 和 Ring0 下的 NtTerminateProcess,

既然要實(shí)現(xiàn)兩個(gè) Hook 的話,我干嘛不將 SSDT Hook 寫成一個(gè)框架呢,

這樣的話,以后我無(wú)論是需要 Hook 哪個(gè) SSDT 中的系統(tǒng)服務(wù),我直接調(diào)用這個(gè) SSDT 框架不就 OK 了,

免得再去重復(fù)造輪子不,所以這里就來(lái)簡(jiǎn)單介紹一下這個(gè) SSDT 框架 ~

當(dāng)然這里談得 SSDT Hook 框架可不是大伙眼里的什么 .Net 框架啊,MVC 框架啊之類的,

沒(méi)那么復(fù)雜,算到底也就是一個(gè) .cpp 和一個(gè) .h 的文件而已,然后再在其中對(duì)外公開(kāi)幾個(gè) API 即 OK 了 ~

????????????????

這里既是使用了 SSDT 的話,而在前一篇博文中也談到了在 ntoskrnl.exe 中導(dǎo)出了 KeServiceDescriptorTable,

但是內(nèi)核中導(dǎo)出歸導(dǎo)出,它導(dǎo)出有個(gè)屁用啊,別個(gè)類型啊什么的都沒(méi)給你,看你怎么在你代碼中使用它 ~

所以我們首先要做的就是如何使用這個(gè) ntoskrnl.exe 中導(dǎo)出的 KeServiceDescriptorTable 了,

不過(guò)好在還有 WRK(當(dāng)然在反匯編,逆向工程里面那些牛的作用也是相當(dāng)?shù)慕o力)的幫助,

我們可以定義下面的代碼來(lái)完成在自己的代碼中使用 KeServiceDescriptorTable 這個(gè)任務(wù):

1: //=====================================================================================// 2: //Name: KSYSTEM_SERVICE_TABLE 和 KSERVICE_TABLE_DESCRIPTOR // 4: //Descripion: 用來(lái)定義 SSDT 結(jié)構(gòu) // 6: //=====================================================================================// 7: typedef struct _KSYSTEM_SERVICE_TABLE 8: { 9: PULONG ServiceTableBase; // SSDT (System Service Dispatch Table)的基地址 10: PULONG ServiceCounterTableBase; // 包含 SSDT 中每個(gè)服務(wù)被調(diào)用的次數(shù) 11: ULONG NumberOfService;???? // 服務(wù)函數(shù)的個(gè)數(shù), NumberOfService * 4 就是整個(gè)地址表的大小 12: ULONG ParamTableBase; // SSPT(System Service Parameter Table)的基地址 13: ? 14: } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE; 15: ? 16: ? 17: typedef struct _KSERVICE_TABLE_DESCRIPTOR 18: { 19: KSYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe 的服務(wù)函數(shù) 20: KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 的服務(wù)函數(shù)(GDI32.dll/User32.dll 的內(nèi)核支持) 21: KSYSTEM_SERVICE_TABLE notUsed1; 22: KSYSTEM_SERVICE_TABLE notUsed2; 23: ? 24: } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR; 25: ? 26: ? 27: //導(dǎo)出由 ntoskrnl.exe 所導(dǎo)出的 SSDT 28: extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

????????

既然是個(gè) SSDT Hook 框架的話,自然需要能夠安裝 Hook,當(dāng)然也需要能夠解除 Hook,

而我們拿什么來(lái)解除 Hook 呢,經(jīng)過(guò)前面的介紹,我們可以知道的是,

SSDT Hook 其實(shí)就是拿我們自己的 Hook 函數(shù)的地址去替換掉原來(lái) SSDT 中保存的系統(tǒng)服務(wù)的地址,

如果 Hook 了某個(gè) API,那就意味著在 SSDT 中指定索引處所保存的系統(tǒng)服務(wù)的地址被修改為了 Hook 函數(shù)的地址,

而如果要解除這個(gè) API 的 Hook,自然就需要將原來(lái)系統(tǒng)中原有的系統(tǒng)服務(wù)的地址寫回 SSDT 指定索引處,

但是我們拿什么來(lái)保存 SSDT Hook 之前的系統(tǒng)服務(wù)的地址呢 ?

????????

由于在 32 位機(jī)器上,一個(gè)入口地址可以用 32 位來(lái)表示,也就可以使用一個(gè) ULONG 類型來(lái)保存,

而由于我們這個(gè)是 SSDT 框架,也就是能夠隨意的 Hook SSDT 中的任意系統(tǒng)服務(wù),

自然為了能成功實(shí)現(xiàn) Hook 的解除,就需要將 SSDT 中在 Hook 之前的每一個(gè)系統(tǒng)服務(wù)的地址保存下來(lái),

根據(jù)上面的總結(jié),這可以通過(guò)一個(gè) ULONG 數(shù)組來(lái)保存就可以了 ~

然后再在 Hook 任意的系統(tǒng)服務(wù)之前,將 SSDT 中的所有系統(tǒng)服務(wù)的地址保存或者說(shuō)是備份到 ULONG 數(shù)組中即可 ~

而后在解除 Hook 時(shí),我們就可以從這個(gè) ULONG 數(shù)組中取出原有系統(tǒng)服務(wù)的地址,

然后將地址寫入到 SSDT 中即可實(shí)現(xiàn) Hook 解除 ~

1: //定義 SSDT(系統(tǒng)服務(wù)描述表) 中服務(wù)個(gè)數(shù)的最大數(shù)目 2: //這里定義為 1024 個(gè),實(shí)際上在 XP SP3 是 0x0128 個(gè) 3: #define MAX_SYSTEM_SERVICE_NUMBER 1024 4: ? 5: //用來(lái)保存 SSDT 中所有的舊的服務(wù)函數(shù)的地址 6: ULONG oldSysServiceAddr[MAX_SYSTEM_SERVICE_NUMBER]; ????????????????

同時(shí)由于要實(shí)現(xiàn)安裝 Hook,解除 Hook,所以自然也要公開(kāi)兩個(gè) API,一個(gè)用來(lái)安裝 Hook,一個(gè)用來(lái)解除 Hook,

根據(jù)上面的這些呢,我們大致可以確定至少需要三個(gè) API:

1: //備份 SSDT 中所有系統(tǒng)服務(wù)的地址 2: VOID BackupSysServicesTable(); 3: ? 4: //安裝 Hook 5: NTSTATUS InstallSysServiceHook(ULONG oldService, ULONG newService); 6: ? 7: //解除 Hook 8: NTSTATUS UnInstallSysServiceHook(ULONG oldService);

?????????????

然后還需要注意的是,SSDT 中保存的地址不是說(shuō)你想寫就可以寫的,

SSDT 在內(nèi)存中是具有只讀屬性保護(hù)的,如果你想修改 SSDT 中的內(nèi)容,你必須先要解除只讀屬性,

也就是要賦予 SSDT 所在的這塊內(nèi)存具有可寫屬性才行,不然回饋你的將是一個(gè)無(wú)情的藍(lán)屏(內(nèi)存寫入錯(cuò)誤) ~

你給了這塊內(nèi)存可寫屬性后,你他媽的寫完后總的把可寫屬性去掉,把別個(gè)恢復(fù)到只讀屬性吧 ~

不然也太不厚道了,用完就不管了 ~ 所以還需要一個(gè)恢復(fù)只讀屬性的 API,

綜述,在 SSDT Hook 框架中又有了兩個(gè) API:

1: //禁止寫入保護(hù),也就是恢復(fù)到只讀 2: VOID DisableWriteProtect(ULONG oldAttr); 3: ? 4: //允許寫入保護(hù),也就是設(shè)置為可寫 5: VOID EnableWriteProtect(PULONG pOldAttr);

??????

然后呢下面就將上面的這些個(gè) API 的實(shí)現(xiàn)代碼給貼出來(lái),個(gè)人覺(jué)得自己的代碼風(fēng)格還算比較好的,

應(yīng)該還是看得下去吧(當(dāng)然這只是我現(xiàn)在的觀點(diǎn),說(shuō)不準(zhǔn)再過(guò)段時(shí)間回頭來(lái)看這些代碼就會(huì)感慨這代碼是給人看的嘛) ~

1: #include "SSDTHook.h" 2: ? 4: //=====================================================================================// 5: //Name: VOID DisableWriteProtect() // 6: // // 7: //Descripion: 用來(lái)去掉內(nèi)存的可寫屬性,從而實(shí)現(xiàn)內(nèi)存只讀 // 8: // // 9: //=====================================================================================// 10: VOID DisableWriteProtect(ULONG oldAttr) 11: { 12: _asm 13: { 14: mov eax, oldAttr 15: mov cr0, eax 16: sti; 17: } 18: } 19: ? 20: ? 21: //=====================================================================================// 22: //Name: VOID EnableWriteProtect() // 23: // // 24: //Descripion: 用來(lái)去掉內(nèi)存的只讀保護(hù),從而實(shí)現(xiàn)可以寫內(nèi)存 // 25: // // 26: //=====================================================================================// 27: VOID EnableWriteProtect(PULONG pOldAttr) 28: { 29: ULONG uAttr; 30: ? 31: _asm 32: { 33: cli; 34: mov eax, cr0; 35: mov uAttr, eax; 36: and eax, 0FFFEFFFFh; // CR0 16 BIT = 0 37: mov cr0, eax; 38: }; 39: ? 40: //保存原有的 CRO 屬性 41: *pOldAttr = uAttr; 42: } 43: ? 44: ? 45: //=====================================================================================// 46: //Name: VOID BackupSysServicesTable() // 47: // // 48: //Descripion: 備份 SSDT 中原有服務(wù)的地址,因?yàn)樵诮獬?Hook 時(shí)需要還原 SSDT 中原有地址 // 49: // // 50: //=====================================================================================// 51: VOID BackupSysServicesTable() 52: { 53: ULONG i; 54: ? 55: for(i = 0; (i < KeServiceDescriptorTable->ntoskrnl.NumberOfService) && (i < MAX_SYSTEM_SERVICE_NUMBER); i++) 56: { 57: oldSysServiceAddr[i] = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[i]; 58: //oldSysServiceAddr[i] = *(PULONG)((ULONG)KeServiceDescriptorTable->ntoskrnl.ServiceTableBase + 4 * i); 59: ? 60: KdPrint(("\Function Information { Number: 0x%04X , Address: %08X}", i, oldSysServiceAddr[i])); 61: } 62: } 63: ? 64: ? 65: //=====================================================================================// 66: //Name: NTSTATUS InstallSysServiceHook() // 67: // // 68: //Descripion: 實(shí)現(xiàn) Hook 的安裝,主要是在 SSDT 中用 newService 來(lái)替換掉 oldService // 69: // // 70: //=====================================================================================// 71: NTSTATUS InstallSysServiceHook(ULONG oldService, ULONG newService) 72: { 73: ULONG uOldAttr = 0; 74: ? 75: EnableWriteProtect(&uOldAttr); 76: ? 77: SYSCALL_FUNCTION(oldService) = newService; 78: //KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[SYSCALL_INDEX(oldService)] = newService; 79: ? 80: DisableWriteProtect(uOldAttr); 81: ? 82: return STATUS_SUCCESS; 83: } 84: ? 85: ? 86: //=====================================================================================// 87: //Name: NTSTATUS UnInstallSysServiceHook() // 88: // // 89: //Descripion: 實(shí)現(xiàn) Hook 的解除,主要是在 SSDT 中用備份下的服務(wù)地址來(lái)替換掉 oldService // 90: // // 91: //=====================================================================================// 92: NTSTATUS UnInstallSysServiceHook(ULONG oldService) 93: { 94: ULONG uOldAttr = 0; 95: ? 96: EnableWriteProtect(&uOldAttr); 97: ? 98: SYSCALL_FUNCTION(oldService) = oldSysServiceAddr[SYSCALL_INDEX(oldService)]; 100: ? 101: DisableWriteProtect(uOldAttr); 102: ? 103: return STATUS_SUCCESS; 104: }

??????????

可以注意到上面有兩個(gè)很重要的宏,即 SYSCALL_FUNCTION 和 SYSCALL_INDEX 宏,

關(guān)于這兩個(gè)宏的具體作用,可以看注釋的 ~

1: //根據(jù) Zw_ServiceFunction 獲取 Zw_ServiceFunction 在 SSDT 中所對(duì)應(yīng)的服務(wù)的索引號(hào) 2: #define SYSCALL_INDEX(ServiceFunction) (*(PULONG)((PUCHAR)ServiceFunction + 1)) 3: ? 4: ? 5: //根據(jù) Zw_ServiceFunction 來(lái)獲得服務(wù)在 SSDT 中的索引號(hào), 6: //然后再通過(guò)該索引號(hào)來(lái)獲取 Nt_ServiceFunction的地址 7: #define SYSCALL_FUNCTION(ServiceFunction) 8: KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[SYSCALL_INDEX(ServiceFunction)]

???????

??????????

4. Ring0 實(shí)現(xiàn)進(jìn)程隱藏:

??????

有了 SSDT Hook 框架后,其實(shí)要實(shí)現(xiàn)進(jìn)程的隱藏是很簡(jiǎn)單的了,

根據(jù)前面的介紹,要想實(shí)現(xiàn)進(jìn)程隱藏,你可以通過(guò) Hook NtQuerySystemInformation 來(lái)實(shí)現(xiàn),

所以剩下的任務(wù)就只需要在我們自己的 Hook 處理函數(shù)中來(lái)將進(jìn)程隱藏掉就 OK 了 ~

由于 NtQuerySystemInformation 這個(gè)系統(tǒng)服務(wù)在 ntddk.h 中并沒(méi)有被聲明,

雖然這個(gè)系統(tǒng)服務(wù)在 ntoskrnl.exe 中被導(dǎo)出了,但是沒(méi)有它的聲明,我們?nèi)匀皇菬o(wú)法使用的,

所以我們就需要手動(dòng)的聲明一下這個(gè)函數(shù) ~

還有需要注意的是,我們?cè)谇懊嬷?#xff0c;在 ntoskrnl.exe 中實(shí)質(zhì)上是存在 ZwQuerySystemInformation

以及 NtQuerySystemInformation 這兩個(gè) API 的,

而在 SSDT Hook 中我們是根據(jù) ZwQuerySystemInformation

來(lái)推算出在 SSDT 中保存有 NtQuerySystemInformation 的地址所在的索引號(hào)的 ~

關(guān)于這個(gè),你可以查看 SYSCALL_INDEX 這個(gè)宏來(lái)再次確認(rèn)一下 ~

然后有了這個(gè)索引號(hào),我們才可以進(jìn)行對(duì) NtQuerySystemInformation 系統(tǒng)服務(wù)的 Hook,

所以在聲明時(shí),我們需要聲明兩個(gè) API,當(dāng)然如果這些 API 在 ntddk.h 中聲明了就不需要了,

但是由于 ZwQuerySystemInformation 和 NtQuerySystemInformation 在 ntddk.h 中都沒(méi)有聲明,

所以需要在我們自己的代碼中手動(dòng)聲明 ~

1: NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation ( 2: __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 3: __out_bcount_opt(SystemInformationLength) PVOID SystemInformation, 4: __in ULONG SystemInformationLength, 5: __out_opt PULONG ReturnLength 6: ); 7: ? 8: typedef NTSTATUS (* NTQUERYSYSTEMINFORMATION)( 9: __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 10: __out_bcount_opt(SystemInformationLength) PVOID SystemInformation, 11: __in ULONG SystemInformationLength, 12: __out_opt PULONG ReturnLength 13: );

????????????????

(暫停一下,肚子餓了 ~ 吃飯去 ~ )

(好,飯給吃了,酒也喝了,精神亢奮中,現(xiàn)在咱繼續(xù)哈 ~ 嘿嘿 ~)

???????

完成了這些聲明后,我們就可以來(lái)實(shí)現(xiàn)自己的 NtQuerySystemInformation Hook 函數(shù)了,

在這個(gè) Hook 函數(shù)中,我們需要對(duì)我們感興趣的進(jìn)程進(jìn)行隱藏 ~

然后這里需要注意的是,我是如何來(lái)實(shí)現(xiàn)對(duì)進(jìn)程隱藏的,

首先我是判斷這個(gè)進(jìn)程的 ID 是否是需要隱藏的進(jìn)程 ID,

這是通過(guò) ValidateProcessNeedHide 函數(shù)來(lái)判斷的 ~ 這個(gè)函數(shù)會(huì)在后面給出 ~

注意結(jié)合代碼中的注釋來(lái)看(雖然注釋比較少 ~ 嘿嘿 ~ )

1: NTSTATUS HookNtQuerySystemInformation ( 2: __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 3: __out_bcount_opt(SystemInformationLength) PVOID SystemInformation, 4: __in ULONG SystemInformationLength, 5: __out_opt PULONG ReturnLength 6: );

?????

1: //=====================================================================================// 2: //Name: NTSTATUS HookNtQuerySystemInformation() // 3: // // 4: //Descripion: 自定義的 NtQuerySystemInformation,用來(lái)實(shí)現(xiàn) Hook Kernel API // 5: // // 6: //=====================================================================================// 7: NTSTATUS HookNtQuerySystemInformation ( 8: __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 9: __out_bcount_opt(SystemInformationLength) PVOID SystemInformation, 10: __in ULONG SystemInformationLength, 11: __out_opt PULONG ReturnLength 12: ) 13: { 14: NTSTATUS rtStatus; 15: ? 16: pOldNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION) 17: oldSysServiceAddr[SYSCALL_INDEX(ZwQuerySystemInformation)]; 18: ? 19: rtStatus = pOldNtQuerySystemInformation(SystemInformationClass, SystemInformation, 20: SystemInformationLength, ReturnLength); 21: if(NT_SUCCESS(rtStatus)) 22: { 23: if(SystemProcessInformation == SystemInformationClass) 24: { 25: PSYSTEM_PROCESS_INFORMATION pPrevProcessInfo = NULL; 26: PSYSTEM_PROCESS_INFORMATION pCurrProcessInfo = 27: (PSYSTEM_PROCESS_INFORMATION)SystemInformation; 28: ? 29: while(pCurrProcessInfo != NULL) 30: { 31: //獲取當(dāng)前遍歷的 SYSTEM_PROCESS_INFORMATION 節(jié)點(diǎn)的進(jìn)程名稱和進(jìn)程 ID 32: ULONG uPID = (ULONG)pCurrProcessInfo->UniqueProcessId; 33: UNICODE_STRING strTmpProcessName = pCurrProcessInfo->ImageName; 34: ? 35: //判斷當(dāng)前遍歷的這個(gè)進(jìn)程是否為需要隱藏的進(jìn)程 36: if(ValidateProcessNeedHide(uPID) != -1) 37: { 38: if(pPrevProcessInfo) 39: { 40: if(pCurrProcessInfo->NextEntryOffset) 41: { 42: //將當(dāng)前這個(gè)進(jìn)程(即要隱藏的進(jìn)程)從 SystemInformation 中摘除(更改鏈表偏移指針實(shí)現(xiàn)) 43: pPrevProcessInfo->NextEntryOffset += pCurrProcessInfo->NextEntryOffset; 44: } 45: else 46: { 47: //說(shuō)明當(dāng)前要隱藏的這個(gè)進(jìn)程是進(jìn)程鏈表中的最后一個(gè) 48: pPrevProcessInfo->NextEntryOffset = 0; 49: } 50: } 51: else 52: { 53: //第一個(gè)遍歷到得進(jìn)程就是需要隱藏的進(jìn)程 54: if(pCurrProcessInfo->NextEntryOffset) 55: { 56: (PCHAR)SystemInformation += pCurrProcessInfo->NextEntryOffset; 57: } 58: else 59: { 60: SystemInformation = NULL; 61: } 62: } 63: } 64: ? 65: //遍歷下一個(gè) SYSTEM_PROCESS_INFORMATION 節(jié)點(diǎn) 66: pPrevProcessInfo = pCurrProcessInfo; 67: ? 68: //遍歷結(jié)束 69: if(pCurrProcessInfo->NextEntryOffset) 70: { 71: pCurrProcessInfo = (PSYSTEM_PROCESS_INFORMATION) 72: (((PCHAR)pCurrProcessInfo) + pCurrProcessInfo->NextEntryOffset); 73: } 74: else 75: { 76: pCurrProcessInfo = NULL; 77: } 78: } 79: } 80: } 81: return rtStatus; 82: }

?????????

既然有了自己的 Hook NtQuerySystemInformation 了,自然我們就可以通過(guò)利用 SSDT 框架來(lái)實(shí)現(xiàn) Hook 了,

這部分的代碼其實(shí)是最簡(jiǎn)單的,因?yàn)槲抑恍枰?DriverEntry 中 Hook 掉 NtQuerySystemInformation 即可,

這里需要注意的是,在執(zhí)行 Hook 之前需要備份一次 SSDT,即在 DriverEntry 中最先需要備份 SSDT ~

當(dāng)然為了保證系統(tǒng)的安全以及其他諸多方面,我們?cè)?DriverUnload 中會(huì)將 Hook 解除掉 ~

從下面的代碼中,我們看到在安裝 Hook 和解除 Hook 時(shí)參數(shù)傳遞進(jìn)去的是 ZwQuerySystemInformation,

這樣很有可能會(huì)讓很多朋友認(rèn)為我們?cè)?Ring0 下的 Hook 的是 ZwQuerySystemInformation,

如果你這樣認(rèn)為的話,那就大錯(cuò)特錯(cuò)了,確實(shí)在 Google 上搜索出的一大堆關(guān)于 SSDT Hook 中,

很多文章都說(shuō)是 Hook 的 ZwQuerySystemInformation,而事實(shí)上這是大錯(cuò)特錯(cuò)的,

我們這里傳入 ZwQuerySystemInformation ,是因?yàn)槲覀冃枰{(diào)用 SYS_INDEX(ZwQuerySystemInformation)

來(lái)獲得 NtQuerySystemInformation 在 SSDT 中的地址所在的索引號(hào),

然后我們根據(jù)這個(gè)索引號(hào)來(lái) Hook NtQuerySystemInformation,

認(rèn)識(shí)到這一點(diǎn)是非常重要的,因?yàn)槲乙婚_(kāi)始也認(rèn)為是 Hook 的 ZwQuerySystemInformation,

從而導(dǎo)致藍(lán)屏了 n 次,在這里非常鄙視那些把文章從別處拷貝過(guò)來(lái)也不加驗(yàn)證就亂發(fā)表的 ~ 害死人 ~ 當(dāng)然也要怪自己懶 ~

???????

??????????

?????????

5. Ring0 實(shí)現(xiàn)進(jìn)程保護(hù):

????????????

有了上面實(shí)現(xiàn)進(jìn)程隱藏的基礎(chǔ),要再來(lái)實(shí)現(xiàn)進(jìn)程保護(hù),其實(shí)也就是過(guò)過(guò)場(chǎng)子了 ~

進(jìn)程保護(hù)呢,上面也說(shuō)了,是要 Hook NtTermianteProcess 這個(gè)系統(tǒng)服務(wù) ~

由于 ZwTerminateProcess 呢,在 ntddk.h 中已經(jīng)聲明了,

所以在我們自己的代碼中就不需要聲明 ZwTermianteProcess 了,

而只需要聲明 NtTerminateProcess 以及 Hook 函數(shù)就 OK 了 ~

1: typedef NTSTATUS (* NTTERMINATEPROCESS)( 2: __in_opt HANDLE ProcessHandle, 3: __in NTSTATUS ExitStatus 4: ); 5: ? 6: NTSTATUS HookNtTerminateProcess( 7: __in_opt HANDLE ProcessHandle, 8: __in NTSTATUS ExitStatus 9: ); 10: ? 11: NTTERMINATEPROCESS pOldNtTerminateProcess;

?????????

至于安裝 Hook 以及卸載 Hook ,都可以根據(jù)進(jìn)程隱藏中的代碼來(lái)完成,因?yàn)橛辛?SSDT Hook 框架,

這一切也就變得很簡(jiǎn)單了,只要在 DriverEntry 中 InstallHook ,然后再在 DriverUnload 中 UnInstallHook 即 OK ~

下面我們重點(diǎn)來(lái)看一看我們自己的 Hook NtTerminateProcess 中是如何實(shí)現(xiàn)進(jìn)程保護(hù)的 ~

進(jìn)程保護(hù)呢其實(shí)也是比較簡(jiǎn)單的,因?yàn)閺纳厦嬉粚拥恼{(diào)用會(huì)傳遞一個(gè)進(jìn)程句柄下來(lái),

而后我們可以根據(jù)這個(gè)進(jìn)程句柄來(lái)獲得進(jìn)程的 EPROCESS 對(duì)象(進(jìn)程位于執(zhí)行體層得對(duì)象),

通過(guò)這個(gè) EPROCESS 對(duì)象,我們就可以獲得這個(gè)請(qǐng)求被結(jié)束的進(jìn)程的 PID,

我們?cè)倥袛噙@個(gè) PID 是否是我們已經(jīng)保護(hù)了的 PID,如果是的話,直接返回一個(gè)請(qǐng)求被拒絕即可,

而如果這個(gè) PID 未被保護(hù),自然我們就交給原來(lái)的 NtTerminateProcess 處理即可 ~

1: //=====================================================================================// 2: //Name: NTSTATUS HookNtTerminateProcess() // 3: // // 4: //Descripion: 自定義的 NtTerminateProcess,用來(lái)實(shí)現(xiàn) Hook Kernel API // 5: // // 6: //=====================================================================================// 7: NTSTATUS HookNtTerminateProcess( 8: __in_opt HANDLE ProcessHandle, 9: __in NTSTATUS ExitStatus 10: ) 11: { 12: ULONG uPID; 13: NTSTATUS rtStatus; 14: PCHAR pStrProcName; 15: PEPROCESS pEProcess; 16: ANSI_STRING strProcName; 17: ? 18: //通過(guò)進(jìn)程句柄來(lái)獲得該進(jìn)程所對(duì)應(yīng)的 FileObject 對(duì)象,由于這里是進(jìn)程對(duì)象,自然獲得的是 EPROCESS 對(duì)象 19: rtStatus = ObReferenceObjectByHandle(ProcessHandle, 20: FILE_READ_DATA, NULL, KernelMode, &pEProcess, NULL); 21: if(!NT_SUCCESS(rtStatus)) 22: { 23: return rtStatus; 24: } 25: ? 26: //保存 SSDT 中原來(lái)的 NtTerminateProcess 地址 27: pOldNtTerminateProcess = 28: (NTTERMINATEPROCESS)oldSysServiceAddr[SYSCALL_INDEX(ZwTerminateProcess)]; 29: ? 30: //通過(guò)該函數(shù)可以獲取到進(jìn)程名稱和進(jìn)程 ID,該函數(shù)在內(nèi)核中實(shí)質(zhì)是導(dǎo)出的(在 WRK 中可以看到) 31: //但是 ntddk.h 中并沒(méi)有到處,所以需要自己聲明才能使用 32: uPID = (ULONG)PsGetProcessId(pEProcess); 33: pStrProcName = (PCHAR)PsGetProcessImageFileName(pEProcess); 34: ? 35: //通過(guò)進(jìn)程名來(lái)初始化一個(gè) ASCII 字符串 36: RtlInitAnsiString(&strProcName, pStrProcName); 37: ? 38: if(ValidateProcessNeedProtect(uPID) != -1) 39: { 40: //確保調(diào)用者進(jìn)程能夠結(jié)束(這里主要是指 taskmgr.exe) 41: if(uPID != (ULONG)PsGetProcessId(PsGetCurrentProcess())) 42: { 43: //如果該進(jìn)程是所保護(hù)的的進(jìn)程的話,則返回權(quán)限不夠的異常即可 44: return STATUS_ACCESS_DENIED; 45: } 46: } 47: ? 48: //對(duì)于非保護(hù)的進(jìn)程可以直接調(diào)用原來(lái) SSDT 中的 NtTerminateProcess 來(lái)結(jié)束進(jìn)程 49: rtStatus = pOldNtTerminateProcess(ProcessHandle, ExitStatus); 50: ? 51: return rtStatus; 52: }

???????????

??????????

6. 隱藏進(jìn)程列表和保護(hù)進(jìn)程列表的維護(hù):

???????

由于需要隱藏的進(jìn)程以及需要被保護(hù)的進(jìn)程都是由應(yīng)用程序傳遞進(jìn)來(lái)的,

也就是說(shuō)這個(gè)內(nèi)核程序是需要和應(yīng)用程序通信的,自然就需要?jiǎng)?chuàng)建一個(gè) Device,

然后我就采用了簡(jiǎn)單的 DeviceIoControl 來(lái)實(shí)現(xiàn)了內(nèi)核程序和應(yīng)用程序的通信,

對(duì)于需要隱藏的進(jìn)程或者是需要保護(hù)的進(jìn)程,其由應(yīng)用程序通過(guò) DeviceIoControl 來(lái)將這個(gè)進(jìn)程的 PID 傳遞給內(nèi)核程序,

然后在內(nèi)核程序中呢,維護(hù)了兩個(gè)數(shù)組,一個(gè)數(shù)組用來(lái)存放需要隱藏的進(jìn)程的 PID,

另外一個(gè)數(shù)組自然就是用來(lái)存放需要保護(hù)的進(jìn)程的 PID,

1: ULONG g_PIDHideArray[MAX_PROCESS_ARRARY_LENGTH]; 2: ULONG g_PIDProtectArray[MAX_PROCESS_ARRARY_LENGTH]; 3: ? 4: ULONG g_currHideArrayLen = 0; 5: ULONG g_currProtectArrayLen = 0;

?????????

為了維護(hù)上面的這兩個(gè)數(shù)組呢,又衍生出了幾個(gè) API,即實(shí)現(xiàn)對(duì)數(shù)組中的 PID 進(jìn)行增刪查 ~

1: //驗(yàn)證 uPID 所代表的進(jìn)程是否存在于隱藏進(jìn)程列表中,即判斷 uPID 這個(gè)進(jìn)程是否需要隱藏 2: ULONG ValidateProcessNeedHide(ULONG uPID); 3: ? 4: //驗(yàn)證 uPID 所代表的進(jìn)程是否存在于保護(hù)進(jìn)程列表中,即判斷 uPID 這個(gè)進(jìn)程是否需要保護(hù) 5: ULONG ValidateProcessNeedProtect(ULONG uPID); 6: ? 7: //往隱藏進(jìn)程列表中插入 uPID 8: ULONG InsertHideProcess(ULONG uPID); 9: ? 10: //從隱藏進(jìn)程列表中移除 uPID 11: ULONG RemoveHideProcess(ULONG uPID); 12: ? 13: //往保護(hù)進(jìn)程列表中插入 uPID 14: ULONG InsertProtectProcess(ULONG uPID); 15: ? 16: //從隱藏進(jìn)程列表中移除 uPID 17: ULONG RemoveProtectProcess(ULONG uPID);

????????

對(duì)于前面談及的 HookNtQuerySystemInformation 和 HookNtTerminateProcess 的話,

需要判斷一個(gè)進(jìn)程是否是需要被保護(hù)或者需要被隱藏的進(jìn)程就是通過(guò)上面的數(shù)組來(lái)完成的,

即判斷一個(gè)進(jìn)程是否需要被隱藏時(shí),只需要判斷這個(gè)進(jìn)程在隱藏列表中是否存在即可,

而對(duì)于實(shí)現(xiàn)進(jìn)程保護(hù)的話,道理也是一樣的 ~

上面說(shuō)過(guò),應(yīng)用程序和內(nèi)核程序的通信是通過(guò) DeviceIoControl 來(lái)完成的,

下面我們就來(lái)看看 DeviceIoControl 的代碼:

1: //=====================================================================================// 2: //Name: NTSTATUS SSDT01DeviceIoControlDispatcher() // 3: // // 4: //Descripion: 分發(fā)函數(shù) // 5: // // 6: //=====================================================================================// 7: NTSTATUS SSDT01DeviceIoControlDispatcher(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) 8: { 9: NTSTATUS rtStatus; 10: ? 11: ULONG uPID; 12: ULONG uInLen; 13: ULONG uOutLen; 14: ULONG uCtrlCode; 15: ? 16: PCHAR pInBuffer; 17: ? 18: PIO_STACK_LOCATION pStack; 19: ? 20: uPID = 0; 21: rtStatus = STATUS_SUCCESS; 22: pStack = IoGetCurrentIrpStackLocation(pIrp); 23: ? 24: uInLen = pStack->Parameters.DeviceIoControl.InputBufferLength; 25: uOutLen = pStack->Parameters.DeviceIoControl.OutputBufferLength; 26: uCtrlCode = pStack->Parameters.DeviceIoControl.IoControlCode; 27: ? 28: //使用緩沖區(qū)方式與應(yīng)用程序進(jìn)行通信 29: pInBuffer = (PCHAR)pIrp->AssociatedIrp.SystemBuffer; 30: 31: if(uInLen >= 4) 32: { 33: //stdlib.h(atol = Array To LONG) 34: uPID = atol(pInBuffer); 35: ? 36: switch(uCtrlCode) 37: { 38: case IO_INSERT_PROTECT_PROCESS: 39: { 40: if(InsertProtectProcess(uPID) == FALSE) 41: { 42: rtStatus = STATUS_PROCESS_IS_TERMINATING; 43: } 44: break; 45: } 46: case IO_REMOVE_PROTECT_PROCESS: 47: { 48: if(RemoveProtectProcess(uPID) == FALSE) 49: { 50: rtStatus = STATUS_PROCESS_IS_TERMINATING; 51: } 52: break; 53: } 54: case IO_INSERT_HIDE_PROCESS: 55: { 56: if(InsertHideProcess(uPID) == FALSE) 57: { 58: rtStatus = STATUS_PROCESS_IS_TERMINATING; 59: } 60: break; 61: } 62: case IO_REMOVE_HIDE_PROCESS: 63: { 64: if(RemoveHideProcess(uPID) == FALSE) 65: { 66: rtStatus = STATUS_PROCESS_IS_TERMINATING; 67: } 68: break; 69: } 70: default: 71: { 72: rtStatus = STATUS_INVALID_VARIANT; 73: break; 74: } 75: } 76: } 77: else 78: { 79: rtStatus = STATUS_INVALID_PARAMETER; 80: } 81: 82: //輸出信息總是為空,即該驅(qū)動(dòng)程序不返回輸出信息 83: pIrp->IoStatus.Status = rtStatus; 84: pIrp->IoStatus.Information = 0; 85: IoCompleteRequest(pIrp, IO_NO_INCREMENT); 86: ? 87: return rtStatus; 88: }

??????????????

?????????

7. 小結(jié):

??????????

這篇博文呢,是承接前一篇博文《進(jìn)程隱藏與進(jìn)程保護(hù)(SSDT Hook 實(shí)現(xiàn))(一)》來(lái)的,

前面的博文主要介紹了 SSDT 是個(gè)什么東西,以及我們做內(nèi)核 Hook 的一些基礎(chǔ),

而這篇博文則完整的介紹了 SSDT Hook 的具體實(shí)現(xiàn),其中涉及到了很多底層的知識(shí)的,

對(duì)于絕大部分的代碼呢,大伙是可以參考代碼來(lái)進(jìn)行理解的,而后我會(huì)將內(nèi)核部分的代碼先公開(kāi)出來(lái) ~

本來(lái)呢是打算將這個(gè) SSDT Hook 做兩篇博文就給結(jié)束得了,

不過(guò)第二篇博文寫了這么長(zhǎng)了,但是在應(yīng)用程序中的實(shí)現(xiàn)都還沒(méi)有開(kāi)始介紹,

而今晚真的又太晚了,再寫下去天就亮了,還說(shuō)要盡量不熬夜的 ~ 唉 ~ 算了,權(quán)當(dāng)周末給自己找個(gè)借口吧 ~

下一篇博文將介紹的是如何在應(yīng)用程序中獲取到所有的進(jìn)程啊,以及應(yīng)用程序如何和內(nèi)核程序設(shè)備進(jìn)行通信之類的知識(shí),

知識(shí)重點(diǎn)是放在 Ring3 了,其中不會(huì)涉及到很多 Ring0 的內(nèi)容了 ~

???????

開(kāi)發(fā)工具以及環(huán)境搭建:

Visual Studio 2010 + VirtualDDK + WDK + VMware + Windows Service 2003 SP1,至于具體環(huán)境的搭建,

可以參考我的博文《驅(qū)動(dòng)程序環(huán)境搭建(VS2010 + WDK + VirtualDDK + VMware)》博文地址如下:

http://www.cnblogs.com/BoyXiao/archive/2011/07/31/2122755.html

???????????

下載?SSDT Hook Source Code

?????????????????????

和前一篇文章一樣,我將我近來(lái)遇到的一些疑問(wèn)放到博文的最后面,看是否有看官遇到過(guò),如果有遇到過(guò)的,

還請(qǐng)不吝賜教 ~ 在下感激不盡 ~

??????????

疑問(wèn) 1:

在 .Net WinForm 中,我有一個(gè)定時(shí)器,然后又有一個(gè)按鈕,

那么對(duì)應(yīng)的就有一個(gè)定時(shí)器 Tick 處理事件,按鈕也會(huì)有一個(gè) Click 事件,

考慮在多核處理器上,有沒(méi)有這樣一種可能,按鈕的 Click 事件和 Tick 處理事件并發(fā)執(zhí)行 ?

如果有的話,大伙一般都是如何做處理的 ?

????????????

疑問(wèn) 2:

大家都有用過(guò) SVN 的,當(dāng)我們安裝好客戶端工具 TortoiseSVN 后,

每次啟動(dòng) PC ,均會(huì)有一個(gè) TSVNCache.exe 的進(jìn)程隨 PC 自動(dòng)啟動(dòng),

請(qǐng)教一下大家這個(gè)進(jìn)程是如何啟動(dòng)的 ?

??????????????

???????????

版權(quán)所有,迎轉(zhuǎn)載,但轉(zhuǎn)載請(qǐng)注明: 轉(zhuǎn)載自??Zachary.XiaoZhen - 夢(mèng)想的天空

總結(jié)

以上是生活随笔為你收集整理的进程隐藏与进程保护(SSDT Hook 实现)(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。