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

字號(hào):

3. 研究系統(tǒng)內(nèi)部機(jī)制
    微軟提供的Windows操作系統(tǒng)是一個(gè)“封閉”的系統(tǒng),很多內(nèi)部資料都沒有公布,我們可以通過Hook技術(shù)來探測(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)的一些未公開,未文檔化的技術(shù)細(xì)節(jié)時(shí)我們都可以使用鉤子技術(shù)。
    4. 其他
    其他如我們要調(diào)試一個(gè)非常麻煩的程序時(shí)就可以使用Hook技術(shù),這樣就可以更好的幫助我們追蹤系統(tǒng)的行動(dòng),更好的了解程序內(nèi)部的執(zhí)行過程。同樣,為了獲取系統(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è)備驅(qū)動(dòng)程序來訪問系統(tǒng)服務(wù)調(diào)度表。如果你對(duì)Windows 2000下基本設(shè)備驅(qū)動(dòng)程序的書寫不太清楚,請(qǐng)查閱相關(guān)的書籍,此處不做介紹。我們先回顧一下Win32內(nèi)核API的實(shí)現(xiàn)流程。
    Windows 2000系統(tǒng)服務(wù)調(diào)用向用戶提供了經(jīng)過包裝的用戶模式的函數(shù)接口(由NTDLL.dll提供)。當(dāng)Kernel32.dll/Advapi32.dll中的函數(shù)執(zhí)行時(shí),先調(diào)用NTDLL.dll中對(duì)應(yīng)的相關(guān)接口,經(jīng)過參數(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指令就是通過服務(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ì)我們來說,定位系統(tǒng)服務(wù)調(diào)度表是實(shí)現(xiàn)Hook的關(guān)鍵。在Windows 2000中有一個(gè)未公開的由ntoskrnl.exe導(dǎo)出的單元:KeServiceDescriptorTable,我們可以通過它來完成對(duì)SSDT的訪問與修改。KeServiceDescriptorTable對(duì)應(yīng)于一個(gè)數(shù)據(jù)結(jié)構(gòu),定義如下:
    typedef struct SystemServiceDescriptorTable
    {
    UINT *ServiceTableBase;
    UINT *ServiceCounterTableBase;
    UINT NumberOfService;
    UCHAR *ParameterTableBase;
    }SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;
    其中ServiceTableBase指向系統(tǒng)服務(wù)程序的地址,ParameterTableBase則指向SSPT中的參數(shù)地址,它們都包含了NumberOfService這么多個(gè)單元。我們只要由KeServiceDescriptorTable找到了我們關(guān)注的系統(tǒng)服務(wù)調(diào)用程序,就可以修改它的ServiceTableBase參數(shù)來實(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)在就不做多說了,大家如果有什么疑問請(qǐng)參閱我以前寫的文章,你可以到FZ5FZ的主頁(http://www.fz5fz.org/)閱讀相關(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)系起來,定義系統(tǒng)調(diào)用:
    __declspec(dllimport) ServiceDescriptorTableEntry KeServiceDescriptorTable;
    #define SYSCALL(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]