Windows服務(wù)調(diào)用機(jī)制
一、序言
Windows系統(tǒng)服務(wù)調(diào)用是存在于Windows系統(tǒng)中的一個(gè)關(guān)鍵接口,常常稱作System Call ,Sysem Service Call 或 System Service Dispatching等,在此我們就權(quán)且稱之為Windows系統(tǒng)服務(wù)調(diào)用,它提供了操作系統(tǒng)環(huán)境由用戶態(tài)切換到內(nèi)核態(tài)的功能。雖然在國(guó)外關(guān)于Windows系統(tǒng)服務(wù)調(diào)用的討論比較多,但卻很少看到比較詳細(xì)的中文資料,希望本文能夠?yàn)楹妥髡咭粯訉?duì)Windows底層感興趣并且是剛剛接觸的朋友提供一些幫助。文章中將以一個(gè)內(nèi)核級(jí)的進(jìn)程監(jiān)視/隱藏工具T-ProcMon為例來(lái)詳細(xì)討論Windows系統(tǒng)服務(wù)調(diào)用的相關(guān)技術(shù)細(xì)節(jié)。另需注意本文討論的技術(shù)僅適用于基于Windows NT內(nèi)核的操作系統(tǒng),并以Windows 2000為例。
二、Windows 2000系統(tǒng)體系結(jié)構(gòu)
微軟Windows 2000是一個(gè)主要面向網(wǎng)絡(luò)服務(wù)器的操作系統(tǒng),因此它和以前大家比較熟悉的Windows 9x有很大的區(qū)別。但是對(duì)于討論一個(gè)因商業(yè)策略而出現(xiàn)的個(gè)人桌面操作系統(tǒng)的確沒(méi)有太大的價(jià)值。所以我們將主要介紹一些關(guān)于NT系統(tǒng)內(nèi)部結(jié)構(gòu)的細(xì)節(jié)。Windows 2000在實(shí)現(xiàn)其自身目標(biāo)的過(guò)程中,我們有必要講解一些它的特性。
1. 可擴(kuò)展性(Extensibility)
Windows 2000操作系統(tǒng)是一個(gè)面向未來(lái)的系統(tǒng),所以它非常注重自身的擴(kuò)展性,因?yàn)樵趯?lái)可能有許多市場(chǎng)等方面的原因?qū)е挛覀儽仨毺砑踊騽h除目前操作系統(tǒng)的一些組件,這就必須要求操作系統(tǒng)有較強(qiáng)的可擴(kuò)展性。為了滿足擴(kuò)充/刪除的各種需求,Windows 2000提供了一個(gè)重要的設(shè)計(jì)思想就是子系統(tǒng)(Subsystem)。我們可以將一些需要擴(kuò)展的操作系統(tǒng)功能作為一個(gè)子系統(tǒng)添加到Windows 2000內(nèi),就像OS/2,POSIX等一樣。當(dāng)然還有一個(gè)特性就是,我們可以通過(guò)為系統(tǒng)服務(wù)調(diào)用添加鉤子來(lái)修改系統(tǒng)的各項(xiàng)行為,這就為我們提供了一個(gè)了解系統(tǒng)內(nèi)部并擴(kuò)展系統(tǒng)功能的機(jī)會(huì)。
2. 可靠性和健壯性(Reliability and Robust)
一個(gè)系統(tǒng)存在的最基本的要求就是它的穩(wěn)定性,沒(méi)有穩(wěn)定的環(huán)境就做不出任何滿意的產(chǎn)品。為了滿足這項(xiàng)要求,Windows 2000提出了基于對(duì)象的訪問(wèn)控制權(quán)限的措施?,F(xiàn)代的大多數(shù)微處理器都支持兩種模式:用戶模式(User/Normal)和內(nèi)核模式(Kernel/Privileged)。操作系統(tǒng)組件和關(guān)鍵的系統(tǒng)組件處于內(nèi)核模式,而一般用戶模式的程序只能訪問(wèn)私有地址空間和執(zhí)行非特權(quán)等級(jí)的指令。如果用戶要調(diào)用一些內(nèi)核組件的功能,就得通過(guò)系統(tǒng)服務(wù)調(diào)用來(lái)實(shí)現(xiàn)。
3. 兼容性(Compatibility)
Intel和Microsoft能夠做到今天的一個(gè)很重要的因素就是他們支持對(duì)過(guò)去存在系統(tǒng)的兼容。這一點(diǎn)非常的關(guān)鍵,沒(méi)有人愿意三天兩頭的更換系統(tǒng),當(dāng)然也很少有人有這個(gè)經(jīng)濟(jì)實(shí)力。Windows 2000為了實(shí)現(xiàn)對(duì)其他系統(tǒng)的兼容,如Dos,16位Windows等,出現(xiàn)了環(huán)境子系統(tǒng)。而在Windows 2000中必須存在的環(huán)境子系統(tǒng)是Win32,它是其他子系統(tǒng)的基礎(chǔ),其他子系統(tǒng)都是一些表面的接口,而實(shí)際上是調(diào)用了Win32提供的接口,而Win32最終也是通過(guò)系統(tǒng)服務(wù)調(diào)用來(lái)與內(nèi)核聯(lián)系的。雖然操作系統(tǒng)為各種環(huán)境子系統(tǒng)提供了不同的動(dòng)態(tài)鏈接庫(kù),而且其中的API函數(shù)名稱往往也是不同的,不過(guò)這個(gè)函數(shù)的最終都是通過(guò)相同的系統(tǒng)服務(wù)調(diào)用進(jìn)入內(nèi)核來(lái)實(shí)現(xiàn)的。
4. 易維護(hù)性(Maintainability)
作為一個(gè)大型的項(xiàng)目,Windows 2000的維護(hù)也成為了一個(gè)大型的工程。而如此巨大的項(xiàng)目沒(méi)有很好的維護(hù)性是無(wú)法發(fā)展下去的。為此,Windows 2000使用了分層的思想,這也是一種操作系統(tǒng)體系結(jié)構(gòu)模型。其中,系統(tǒng)服務(wù)調(diào)用將系統(tǒng)的內(nèi)核模式代碼和用戶模式代碼隔離開(kāi)來(lái),子系統(tǒng)使用系統(tǒng)服務(wù)調(diào)用為用戶提供應(yīng)用程序編程接口(API),而系統(tǒng)服務(wù)調(diào)用向下調(diào)用執(zhí)行體實(shí)現(xiàn)各項(xiàng)功能。
就像在上文我們提到的操作系統(tǒng)存在的兩種模式,這是建立在處理器的基礎(chǔ)之上的。按理說(shuō),一般處理器可以提供從Ring0到Ring3的四種處理器模式,但是它們必須提供至少兩種,那就是Ring0和Ring3。而一些特殊處理器指令只能在內(nèi)核模式執(zhí)行,而一些地址空間必須在內(nèi)核模式才可以被訪問(wèn)。Windows 2000就利用了這個(gè)特點(diǎn),將操作系統(tǒng)和其他關(guān)鍵組件保護(hù)起來(lái),只有在內(nèi)核模式才可以訪問(wèn)執(zhí)行,而一般的用戶程序就只能在用戶態(tài)執(zhí)行咯,這樣就可以避免一些用戶程序?qū)Σ僮飨到y(tǒng)代碼的破壞,也就是大家看到的Windows 2000明顯比Windows 9x穩(wěn)定得多的主要原因。下面我們給出了Windows 2000的體系結(jié)構(gòu)簡(jiǎn)圖:
系統(tǒng)支持進(jìn)程,服務(wù)進(jìn)程,應(yīng)用程序,環(huán)境子系統(tǒng) 應(yīng)用程序編程接口 基于NTDLL.dll的本地系統(tǒng)服務(wù) (用戶模式) ----------------------------------------- 系統(tǒng)服務(wù)調(diào)用(內(nèi)核模式) 執(zhí)行體 系統(tǒng)內(nèi)核,設(shè)備驅(qū)動(dòng)程序 硬件抽象層
三、Windows 2000本機(jī)系統(tǒng)服務(wù)(Native API)
Windows 2000本機(jī)系統(tǒng)服務(wù)又稱為Windows本機(jī)應(yīng)用程序編程接口,它是由執(zhí)行體(Executive)為用戶模式和內(nèi)核模式的程序提供的系統(tǒng)服務(wù)集。它包含兩種類型的函數(shù):Windows 執(zhí)行系統(tǒng)服務(wù)的系統(tǒng)服務(wù)調(diào)度占位程序;子系統(tǒng),子系統(tǒng)DLL和其他本機(jī)映像使用的內(nèi)部支持函數(shù)。
從用戶模式調(diào)用本機(jī)系統(tǒng)服務(wù)是通過(guò)NTDLL.dll來(lái)實(shí)現(xiàn)的。表面上,Win32函數(shù)為編程人員提供了很多接口來(lái)實(shí)現(xiàn)我們想要的功能,但是這些Win32函數(shù)只不過(guò)是本機(jī)應(yīng)用程序編程接口的一個(gè)包裝器而已,它們將本機(jī)API包裝起來(lái),調(diào)用本機(jī)系統(tǒng)服務(wù)來(lái)實(shí)現(xiàn)用戶期望的功能。也就是說(shuō)NTDLL.dll只是系統(tǒng)服務(wù)調(diào)用接口在用戶模式下的一個(gè)外殼。關(guān)于用戶模式下的Windows本機(jī)系統(tǒng)服務(wù)的相關(guān)信息,請(qǐng)參見(jiàn)我以前寫(xiě)的一篇文章《探測(cè)Windows2K/XP/2003本機(jī)系統(tǒng)信息》。
我們?cè)僬務(wù)剰膬?nèi)核模式調(diào)用系統(tǒng)服務(wù)吧,這時(shí)就不是由NTDLL.dll導(dǎo)出系統(tǒng)服務(wù)調(diào)用的函數(shù)接口了,而是由ntoskrnl.exe來(lái)實(shí)現(xiàn)的,它會(huì)提供兩種形式的函數(shù):ZwXxx和NtXxx,在此我們就不多說(shuō)了。大家應(yīng)該注意到了,在上面我們介紹的Windows 2000系統(tǒng)體系結(jié)構(gòu)中的系統(tǒng)服務(wù)調(diào)用,執(zhí)行體和內(nèi)核都是存在于ntoskrnl.exe(在多處理器中為ntkrnlmp.exe)之中,并且是分層的。
四、Windows 2000系統(tǒng)服務(wù)調(diào)用機(jī)制
Windows 2000的陷阱調(diào)度(Trap Dispatching)機(jī)制包括了:中斷(Interrupt),延遲過(guò)程調(diào)用(Deferred Procedure Call),異步過(guò)程調(diào)用(Asynchronous Procedure Call),異常調(diào)度(Exception Dispatching)和系統(tǒng)服務(wù)調(diào)用。在Intel x86的Windows 2000系統(tǒng)中,處理器執(zhí)行int 0x2e指令來(lái)激活Windows系統(tǒng)服務(wù)調(diào)用;在Intel x86的Windows XP系統(tǒng)中處理器卻是通過(guò)執(zhí)行sysenter指令使系統(tǒng)陷入系統(tǒng)服務(wù)調(diào)用程序中;而在AMD的Windows XP中使用了指令syscall來(lái)實(shí)現(xiàn)同樣的功能。我們暫時(shí)使用x86的Windows 2000為例來(lái)演示。我們先給出一個(gè)系統(tǒng)服務(wù)調(diào)用的模型:
mov eax, ServiceId lea edx, ParameterTableint 2ehret ParamTableBytes
其中,ServiceId清楚的說(shuō)明了傳遞給系統(tǒng)服務(wù)調(diào)用的系統(tǒng)服務(wù)號(hào),內(nèi)核使用這個(gè)標(biāo)識(shí)符來(lái)查找系統(tǒng)服務(wù)調(diào)度表(System Service Dispath Table)中的對(duì)應(yīng)系統(tǒng)服務(wù)信息。在系統(tǒng)服務(wù)調(diào)度表中的每一項(xiàng)包含了一個(gè)指向系統(tǒng)服務(wù)程序的指針,我們Hook時(shí)就是修改這個(gè)指針使其指向我們自定義的系統(tǒng)服務(wù)的地址。ParameterTable是傳遞的參數(shù),系統(tǒng)服務(wù)調(diào)用程序KiSystemService必須嚴(yán)格校驗(yàn)傳遞的每一個(gè)參數(shù),并將其參數(shù)從線程的用戶堆棧中復(fù)制到系統(tǒng)的核心堆棧以備使用。由于執(zhí)行int指令會(huì)導(dǎo)致陷阱發(fā)生,所以在Windows 2000內(nèi)的中斷描述表(IDT = Interrupt Descriptor Table)中的0x2e項(xiàng)指向了系統(tǒng)服務(wù)調(diào)用程序。最后返回的ParamTableBytes是關(guān)于參數(shù)個(gè)數(shù)的信息。
現(xiàn)在我們已經(jīng)看得出來(lái)了,系統(tǒng)服務(wù)調(diào)用只是一個(gè)接口,它提供了將用戶模式下的請(qǐng)求轉(zhuǎn)發(fā)到Windows 2000內(nèi)核的功能,并引發(fā)處理器模式的切換。在用戶看來(lái),系統(tǒng)服務(wù)調(diào)用接口就是Windows內(nèi)核組件功能實(shí)現(xiàn)對(duì)外的一個(gè)界面。系統(tǒng)服務(wù)調(diào)用接口定義了Windows內(nèi)核提供的大量服務(wù)。五、Windows 2000系統(tǒng)服務(wù)調(diào)用類型
在Windows 2000中默認(rèn)存在兩個(gè)系統(tǒng)服務(wù)調(diào)度表,它們對(duì)應(yīng)了兩類不同的系統(tǒng)服務(wù)。這兩個(gè)系統(tǒng)服務(wù)調(diào)度表分別是:KeServiceDescriptorTable和KeServiceDescriptorTableShadow。
Windows 2000執(zhí)行程序服務(wù)對(duì)應(yīng)于NTDLL.dll為我們提供的系統(tǒng)服務(wù)調(diào)用。子系統(tǒng)通過(guò)調(diào)用NTDLL.dll中的函數(shù)接口來(lái)實(shí)現(xiàn)它們需要的功能。系統(tǒng)服務(wù)調(diào)度表KeServiceDescriptorTable定義了在ntoskrln.exe中實(shí)現(xiàn)的系統(tǒng)服務(wù),通常在kernel32.dll/advapi32.dll中提供的函數(shù)接口均是調(diào)用的這個(gè)系統(tǒng)服務(wù)調(diào)度表中。
同時(shí)存在于Windows 2000操作系統(tǒng)中還有在Win32k.sys中實(shí)現(xiàn)的相關(guān)Win32USER和GDI函數(shù),它們是屬于另一類系統(tǒng)服務(wù)調(diào)用。與之對(duì)應(yīng)的系統(tǒng)服務(wù)調(diào)度表為KeServiceDescriptorTableShadow,它提供了內(nèi)核模式實(shí)現(xiàn)的USER和GDI服務(wù)。函數(shù)KeAddSystemServiceTable允許Win32.sys和其他設(shè)備驅(qū)動(dòng)程序添加系統(tǒng)服務(wù)表。除了Win32k.sys服務(wù)表外,使用KeAddSystemServiceTable添加的服務(wù)表會(huì)被同時(shí)復(fù)制到KeServiceDescriptorTable和KeServiceDescriptorTableShadow中去。
我們可以看出這兩類函數(shù)實(shí)現(xiàn)在服務(wù)調(diào)度上的區(qū)別:Win32內(nèi)核API經(jīng)過(guò)Kernel32.dll/advapi32.dll進(jìn)入NTDLL.dll后使用int 0x2e中斷進(jìn)入內(nèi)核,最后在Ntoskrnl.exe中實(shí)現(xiàn)了真正的函數(shù)調(diào)用;Win32 USER/GDI API直接通過(guò)User32.dll/Gdi32.dll進(jìn)入了內(nèi)核,最后卻是在Win32k.sys中實(shí)現(xiàn)了真正的函數(shù)調(diào)用。在此我們只討論與NTDLL.dll相關(guān)的函數(shù),也就是我們例子中處理的函數(shù)。
六、Hook系統(tǒng)服務(wù)調(diào)用的作用
鉤子(Hooking)是一種攔截/監(jiān)聽(tīng)可執(zhí)行代碼在執(zhí)行過(guò)程中相關(guān)信息的一種通用機(jī)制。它使我們了解系統(tǒng)內(nèi)部結(jié)構(gòu),運(yùn)作機(jī)制甚至修改系統(tǒng)行為的想法成為可能。在一個(gè)像M$存在的世界里,Windows的很多內(nèi)部信息我們都是無(wú)法得知的,因?yàn)閃indows不是Linux,但這并不意味著我們就此放棄!只要開(kāi)動(dòng)你的大腦,很多事情都會(huì)變成可能。
1. 事件追蹤
你想知道Windows在什么時(shí)候會(huì)打開(kāi)一個(gè)進(jìn)程嗎?你想知道Windows任務(wù)管理器中進(jìn)程相關(guān)信息的獲取調(diào)用了哪些函數(shù)嗎?我們都可以使用Hook技術(shù)來(lái)實(shí)現(xiàn)這些你想要的信息。我們可以追蹤ZwOpenProcess的執(zhí)行情況,我們同樣也可以追蹤ZwQueryInformationProcess的執(zhí)行情況,包括傳遞的參數(shù)和返回的結(jié)果。大家可以看到本文相關(guān)的程序T-ProcMon就是一個(gè)進(jìn)程監(jiān)視工具,它會(huì)追蹤系統(tǒng)中與進(jìn)程相關(guān)的各種信息。在某些我們期望的事件發(fā)生時(shí),程序會(huì)通知用戶發(fā)生了什么,這也是我們期望看到的結(jié)果。
2. 修改系統(tǒng)行為
操作系統(tǒng)為我們提供了一些通用的功能,如查詢系統(tǒng)進(jìn)程信息ZwQuerySystemInformation(SystemInformationClass == 5),它會(huì)返回系統(tǒng)中當(dāng)前所有進(jìn)程/線程的相關(guān)信息。如果我們希望隱藏一些特殊的進(jìn)程那該怎么辦呢?那就是修改系統(tǒng)服務(wù)調(diào)用,也就是修改ZwQuerySystemInformation的行為。在查詢系統(tǒng)進(jìn)程時(shí),系統(tǒng)會(huì)返回一個(gè)進(jìn)程信息隊(duì)列,每個(gè)單元對(duì)應(yīng)一個(gè)進(jìn)程,如果我們想隱藏其中的某個(gè)進(jìn)程,只須修改隊(duì)列中的某些數(shù)據(jù),然后返回給上層函數(shù),它們就不會(huì)發(fā)現(xiàn)Xxx.exe進(jìn)程存在于系統(tǒng)之中了。
3. 研究系統(tǒng)內(nèi)部機(jī)制
微軟提供的Windows操作系統(tǒng)是一個(gè)“封閉”的系統(tǒng),很多內(nèi)部資料都沒(méi)有公布,我們可以通過(guò)Hook技術(shù)來(lái)探測(cè)系統(tǒng)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)和運(yùn)行機(jī)制,學(xué)習(xí)操作系統(tǒng)內(nèi)部的操作方式?;贖ook的Windows內(nèi)核黑客技術(shù)(Kernel Hacking)是非常之流行和有效,在我們探測(cè)系統(tǒng)的一些未公開(kāi),未文檔化的技術(shù)細(xì)節(jié)時(shí)我們都可以使用鉤子技術(shù)。
4. 其他
其他如我們要調(diào)試一個(gè)非常麻煩的程序時(shí)就可以使用Hook技術(shù),這樣就可以更好的幫助我們追蹤系統(tǒng)的行動(dòng),更好的了解程序內(nèi)部的執(zhí)行過(guò)程。同樣,為了獲取系統(tǒng)的一些特殊性能數(shù)據(jù),我們也可以在特定的情況下使用Hook技術(shù)。
七、Hook系統(tǒng)服務(wù)調(diào)用的實(shí)現(xiàn)
在此我們討論Hook的對(duì)象僅限于由Windows 2000的ntoskrnl.exe提供的系統(tǒng)服務(wù)調(diào)用。Windows 2000系統(tǒng)服務(wù)調(diào)用為內(nèi)核模式的代碼,所以我們必須書(shū)寫(xiě)設(shè)備驅(qū)動(dòng)程序來(lái)訪問(wèn)系統(tǒng)服務(wù)調(diào)度表。如果你對(duì)Windows 2000下基本設(shè)備驅(qū)動(dòng)程序的書(shū)寫(xiě)不太清楚,請(qǐng)查閱相關(guān)的書(shū)籍,此處不做介紹。我們先回顧一下Win32內(nèi)核API的實(shí)現(xiàn)流程。
Windows 2000系統(tǒng)服務(wù)調(diào)用向用戶提供了經(jīng)過(guò)包裝的用戶模式的函數(shù)接口(由NTDLL.dll提供)。當(dāng)Kernel32.dll/Advapi32.dll中的函數(shù)執(zhí)行時(shí),先調(diào)用NTDLL.dll中對(duì)應(yīng)的相關(guān)接口,經(jīng)過(guò)參數(shù)檢查后使用int 0x2e指令進(jìn)入內(nèi)核模式,傳遞相關(guān)的服務(wù)號(hào)和參數(shù)列表。在ntoskrnl.exe中維護(hù)著兩個(gè)表系統(tǒng)服務(wù)調(diào)度表(System Service Dispath Table)和系統(tǒng)服務(wù)參數(shù)表(System Service Parameter Table),其中int 0x2e指令就是通過(guò)服務(wù)號(hào)在SSDT中查詢相關(guān)系統(tǒng)服務(wù)程序指針的?,F(xiàn)在我們已經(jīng)清楚了每個(gè)系統(tǒng)服務(wù)調(diào)用都對(duì)應(yīng)一個(gè)服務(wù)號(hào),同時(shí)也對(duì)應(yīng)一個(gè)服務(wù)程序的地址!如果我們修改SSDT中的某個(gè)系統(tǒng)服務(wù)程序的入口地址為指向我們自定義的函數(shù)地址,在執(zhí)行完我們的代碼后再執(zhí)行原始系統(tǒng)服務(wù)地址處的代碼,這不就實(shí)現(xiàn)了對(duì)系統(tǒng)服務(wù)調(diào)用的了Hook嗎?
對(duì)我們來(lái)說(shuō),定位系統(tǒng)服務(wù)調(diào)度表是實(shí)現(xiàn)Hook的關(guān)鍵。在Windows 2000中有一個(gè)未公開(kāi)的由ntoskrnl.exe導(dǎo)出的單元:KeServiceDescriptorTable,我們可以通過(guò)它來(lái)完成對(duì)SSDT的訪問(wèn)與修改。KeServiceDescriptorTable對(duì)應(yīng)于一個(gè)數(shù)據(jù)結(jié)構(gòu),定義如下:
typedef struct SystemServiceDescriptorTable{UINT*ServiceTableBase;UINT*ServiceCounterTableBase;UINTNumberOfService;UCHAR*ParameterTableBase;}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;
其中ServiceTableBase指向系統(tǒng)服務(wù)程序的地址,ParameterTableBase則指向SSPT中的參數(shù)地址,它們都包含了NumberOfService這么多個(gè)單元。我們只要由KeServiceDescriptorTable找到了我們關(guān)注的系統(tǒng)服務(wù)調(diào)用程序,就可以修改它的ServiceTableBase參數(shù)來(lái)實(shí)現(xiàn)對(duì)相關(guān)系統(tǒng)服務(wù)調(diào)用的Hook了!
八、T-ProcMon-1.0 關(guān)鍵源碼分析1. 基于CUI的用戶模式控制程序
由于在此之前我已經(jīng)對(duì)Win32的系統(tǒng)服務(wù)進(jìn)行了詳細(xì)的介紹,現(xiàn)在就不做多說(shuō)了,大家如果有什么疑問(wèn)請(qǐng)參閱我以前寫(xiě)的文章,你可以到FZ5FZ的主頁(yè)閱讀相關(guān)文章,或下載相關(guān)源代碼。
2. 基于設(shè)備驅(qū)動(dòng)的Hook代碼
定義在用戶模式與內(nèi)核模式程序間通信的命令代碼:
#define PROCMON_MONITOR (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x01,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_HIDDEN; (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x02,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_HOOK(ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x03,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_UNHOOK; (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x04,METHOD_BUFFERED,FILE_ANY_ACCESS)
將KeServiceDescriptorTable與相關(guān)數(shù)據(jù)結(jié)構(gòu)聯(lián)系起來(lái),定義系統(tǒng)調(diào)用:
__declspec(dllimport); ServiceDescriptorTableEntry KeServiceDescriptorTable;#define SYSCALL(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
定義各種未公開(kāi)的函數(shù),如ZwQuerySystemInformation:
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(IN ULONG SystemInformationClass,IN OUT PVOID SystemInformation,IN ULONG SystemInformaitonLength,OUTPULONGReturnLength OPTIONAL);
修改系統(tǒng)服務(wù)調(diào)用,保存原始的入口地址,修改為我們自定義的程序入口地址,如ZwQuerySystemInformation:
OldZwQuerySystemInformation; = (ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation));_asm cli(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation))= NewZwQuerySystemInformation;_asm sti
解除鉤子,還原系統(tǒng)服務(wù)調(diào)用:
_asm cli(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation))= OldZwQuerySystemInformation;_asm sti
調(diào)用原始的系統(tǒng)服務(wù)程序代碼:
NtStatus = (OldZwQuerySystemInformation)(SystemInformationClass,SystemInformation,SystemInformaitonLength,ReturnLength);
隱藏進(jìn)程,既是修改系統(tǒng)返回的數(shù)據(jù)隊(duì)列中相關(guān)項(xiàng)的偏移量使起指向需要隱藏進(jìn)程的下一個(gè)單元,也就是說(shuō)跳過(guò)我們需要隱藏進(jìn)程的單元:
if(RtlCompareUnicodeString(&pCurrentNK->Name,&ProcCur->ProcessName,TRUE) == 0){RtlUnicodeStringToAnsiString(&ProcNameA,&pCurrentNK->Name,TRUE);DbgPrint('Hidden Process Name: %sn',ProcNameA.Buffer);if(ProcPre != NULL){; if(ProcCur->NextEntryDelta != 0){ProcPre->NextEntryDelta += ProcCur->NextEntryDelta;}else{ProcPre->NextEntryDelta; = 0;}}else{if(ProcCur->NextEntryDelta != 0){SystemInformation = (PSYSTEM_PROCESSES)((PTSTR)ProcCur + ProcCur->NextEntryDelta);}else{ SystemInformation = NULL;}}break;}
