剖析Windows系統(tǒng)服務(wù)調(diào)用機制(中)

字號:

四> Windows 2000系統(tǒng)服務(wù)調(diào)用機制
    Windows 2000的陷阱調(diào)度(Trap Dispatching)機制包括了:中斷(Interrupt),延遲過程調(diào)用(Deferred Procedure Call),異步過程調(diào)用(Asynchronous Procedure Call),異常調(diào)度(Exception Dispatching)和系統(tǒng)服務(wù)調(diào)用。在Intel x86的Windows 2000系統(tǒng)中,處理器執(zhí)行int 0x2e指令來激活Windows系統(tǒng)服務(wù)調(diào)用;在Intel x86的Windows XP系統(tǒng)中處理器卻是通過執(zhí)行sysenter指令使系統(tǒng)陷入系統(tǒng)服務(wù)調(diào)用程序中;而在AMD的Windows XP中使用了指令syscall來實現(xiàn)同樣的功能。我們暫時使用x86的Windows 2000為例來演示。我們先給出一個系統(tǒng)服務(wù)調(diào)用的模型:
    mov eax, ServiceId
    lea edx, ParameterTable
    int 2eh
    ret ParamTableBytes
    其中,ServiceId清楚的說明了傳遞給系統(tǒng)服務(wù)調(diào)用的系統(tǒng)服務(wù)號,內(nèi)核使用這個標識符來查找系統(tǒng)服務(wù)調(diào)度表(System Service Dispath Table)中的對應(yīng)系統(tǒng)服務(wù)信息。在系統(tǒng)服務(wù)調(diào)度表中的每一項包含了一個指向系統(tǒng)服務(wù)程序的指針,我們Hook時就是修改這個指針使其指向我們自定義的系統(tǒng)服務(wù)的地址。ParameterTable是傳遞的參數(shù),系統(tǒng)服務(wù)調(diào)用程序KiSystemService必須嚴格校驗傳遞的每一個參數(shù),并將其參數(shù)從線程的用戶堆棧中復(fù)制到系統(tǒng)的核心堆棧以備使用。由于執(zhí)行int指令會導(dǎo)致陷阱發(fā)生,所以在Windows 2000內(nèi)的中斷描述表(IDT = Interrupt Descriptor Table)中的0x2e項指向了系統(tǒng)服務(wù)調(diào)用程序。最后返回的ParamTableBytes是關(guān)于參數(shù)個數(shù)的信息。
    現(xiàn)在我們已經(jīng)看得出來了,系統(tǒng)服務(wù)調(diào)用只是一個接口,它提供了將用戶模式下的請求轉(zhuǎn)發(fā)到Windows 2000內(nèi)核的功能,并引發(fā)處理器模式的切換。在用戶看來,系統(tǒng)服務(wù)調(diào)用接口就是Windows內(nèi)核組件功能實現(xiàn)對外的一個界面。系統(tǒng)服務(wù)調(diào)用接口定義了Windows內(nèi)核提供的大量服務(wù)。
    五> Windows 2000系統(tǒng)服務(wù)調(diào)用類型
    在Windows 2000中默認存在兩個系統(tǒng)服務(wù)調(diào)度表,它們對應(yīng)了兩類不同的系統(tǒng)服務(wù)。這兩個系統(tǒng)服務(wù)調(diào)度表分別是:KeServiceDescriptorTable和KeServiceDescriptorTableShadow。
    Windows 2000執(zhí)行程序服務(wù)對應(yīng)于NTDLL.dll為我們提供的系統(tǒng)服務(wù)調(diào)用。子系統(tǒng)通過調(diào)用NTDLL.dll中的函數(shù)接口來實現(xiàn)它們需要的功能。系統(tǒng)服務(wù)調(diào)度表KeServiceDescriptorTable定義了在ntoskrln.exe中實現(xiàn)的系統(tǒng)服務(wù),通常在kernel32.dll/advapi32.dll中提供的函數(shù)接口均是調(diào)用的這個系統(tǒng)服務(wù)調(diào)度表中。
    同時存在于Windows 2000操作系統(tǒng)中還有在Win32k.sys中實現(xiàn)的相關(guān)Win32USER和GDI函數(shù),它們是屬于另一類系統(tǒng)服務(wù)調(diào)用。與之對應(yīng)的系統(tǒng)服務(wù)調(diào)度表為KeServiceDescriptorTableShadow,它提供了內(nèi)核模式實現(xiàn)的USER和GDI服務(wù)。函數(shù)KeAddSystemServiceTable允許Win32.sys和其他設(shè)備驅(qū)動程序添加系統(tǒng)服務(wù)表。除了Win32k.sys服務(wù)表外,使用KeAddSystemServiceTable添加的服務(wù)表會被同時復(fù)制到KeServiceDescriptorTable和KeServiceDescriptorTableShadow中去。
    我們可以看出這兩類函數(shù)實現(xiàn)在服務(wù)調(diào)度上的區(qū)別:Win32內(nèi)核API經(jīng)過Kernel32.dll/advapi32.dll進入NTDLL.dll后使用int 0x2e中斷進入內(nèi)核,最后在Ntoskrnl.exe中實現(xiàn)了真正的函數(shù)調(diào)用;Win32 USER/GDI API直接通過User32.dll/Gdi32.dll進入了內(nèi)核,最后卻是在Win32k.sys中實現(xiàn)了真正的函數(shù)調(diào)用。在此我們只討論與NTDLL.dll相關(guān)的函數(shù),也就是我們例子中處理的函數(shù)。
    六> Hook系統(tǒng)服務(wù)調(diào)用的作用
    鉤子(Hooking)是一種攔截/監(jiān)聽可執(zhí)行代碼在執(zhí)行過程中相關(guān)信息的一種通用機制。它使我們了解系統(tǒng)內(nèi)部結(jié)構(gòu),運作機制甚至修改系統(tǒng)行為的想法成為可能。在一個像M$存在的世界里,Windows的很多內(nèi)部信息我們都是無法得知的,因為Windows不是Linux,但這并不意味著我們就此放棄!只要開動你的大腦,很多事情都會變成可能。
    1. 事件追蹤
    你想知道Windows在什么時候會打開一個進程嗎?你想知道Windows任務(wù)管理器中進程相關(guān)信息的獲取調(diào)用了哪些函數(shù)嗎?我們都可以使用Hook技術(shù)來實現(xiàn)這些你想要的信息。我們可以追蹤ZwOpenProcess的執(zhí)行情況,我們同樣也可以追蹤ZwQueryInformationProcess的執(zhí)行情況,包括傳遞的參數(shù)和返回的結(jié)果。大家可以看到本文相關(guān)的程序T-ProcMon就是一個進程監(jiān)視工具,它會追蹤系統(tǒng)中與進程相關(guān)的各種信息。在某些我們期望的事件發(fā)生時,程序會通知用戶發(fā)生了什么,這也是我們期望看到的結(jié)果。
    2. 修改系統(tǒng)行為
    操作系統(tǒng)為我們提供了一些通用的功能,如查詢系統(tǒng)進程信息ZwQuerySystemInformation(SystemInformationClass == 5),它會返回系統(tǒng)中當前所有進程/線程的相關(guān)信息。如果我們希望隱藏一些特殊的進程那該怎么辦呢?那就是修改系統(tǒng)服務(wù)調(diào)用,也就是修改ZwQuerySystemInformation的行為。在查詢系統(tǒng)進程時,系統(tǒng)會返回一個進程信息隊列,每個單元對應(yīng)一個進程,如果我們想隱藏其中的某個進程,只須修改隊列中的某些數(shù)據(jù),然后返回給上層函數(shù),它們就不會發(fā)現(xiàn)Xxx.exe進程存在于系統(tǒng)之中了。