Kmd教程1 For FASM

 

 KmdKit的全稱是Kernel Mode Driver development Kit for assembly language programmers,即內核模式驅動程序彙編開發包。

 

1.Kernel Mode驅動程序基礎

    本教程講述瞭如何在Windows NT爲基礎的操作系統上用Win32彙編開發KMD,包括NT4.0、2000、XP和2003等操作系統。開發Windows 95/98/ME使用的VxD驅動程序方面的知識並不在本教程講述的範圍內,另外,毫無疑問本教程並不那麼完美,可能還包含了諸多未發現的錯誤,如果您發現了問題,請告知作者,畢竟作者的母語並不是英語,把它翻譯成英文已經夠難爲我了(注:原作者是俄國人也),也感謝masquer和Volodya的校對工作。

 

    注意本文作者是將MASM翻譯成FASM,Thanks for 羅雲彬

 

1.1 KMD結構概述

 

     根據地址空間、代碼權限和職責的不同,Windows NT內部劃分爲兩個截然不同的部分。

 


   
地址空間的享用方式也非常容易理解,整個32位系統的4GB內容被劃分爲兩個相等的部分,用戶模式(user-mode)的進程使用的地址空間被映射到低位的2GB上(地址範圍00000000 - 7FFFFFFFh),而高位的2GB(地址範圍80000000h - 0FFFFFFFFh)則供操作系統的組成部分來使用,如設備驅動程序、系統內存池、系統使用的數據結構等,在這部分中,內存共享的權限和職責等方面就要複雜一點了。

 下面就是用戶模式進程的一些簡單分類:


◎ 系統支持進程--如Logon進程(位於/%SystemRoot%/System32/Winlogon.exe)
◎ 服務進程--如Spooler進程(位於/%SystemRoot%/System32/spoolsv.exe)
◎ 用戶應用程序--任何Win32、Windows 3.1、DOS、POSIX或者OS/2程序
◎ 子系統--Windows內置3個子系統:Win32(位於/%SystemRoot%/System32/Csrss.exe)、POSIX子系統(位於/%SystemRoot%/System32/Psxss.exe)和OS/2子系統(位於/%SystemRoot%/System32/Os2ss.exe),在Windows XP以及後續的操作系統中,POSIX和OS/2子系統已經被去掉了。


 


 而下面是內核模式的一些模塊:


◎ 運行模塊--內存管理、進程和線程的管理、安全機制等
◎ 內核--線程調度、中斷、異常的分派等(運行模塊和內核位於/%SystemRoot%/System32/Ntoskrnl.exe)
◎ 設備驅動程序--硬件設備驅動程序、文件系統和網絡驅動程序
◎ 硬件抽象層(Hardware Abstraction Layer, HAL)--將內核、設備驅動程序和運行模塊和具體的硬件平臺隔離開(位於/%SystemRoot%/System32/Hal.dll)
◎ 窗口和圖形系統--實現GUI函數,如處理窗口、用戶界面的控制和繪畫等(位於/%SystemRoot%/System32/Win32k.sys)

 

 、

 

 

 Windows NT結構簡圖

 

1.1.2 內核模式和用戶模式

    Intel x86體系結構的處理器定義了4個級別的權限(稱爲Ring),Windows系統使用了Ring0(供特權模式使用)和Ring3(供用戶模式使用),Windows系統只使用了2個級別的權限級別的原因是爲了和其他一些硬件系統兼容,這些硬件系統只有2個級別的權限,如Compaq Alpha和Silicon Graphics MIPS等。

 

 

  每個用戶模式的進程有其私有的地址空間,這些進程在最低的權限級別下運行(稱爲Ring3或者用戶模式),它們不允許執行CPU的特權指令,對系統所屬的數據、地址空間以及硬件等的訪問也是被嚴格限制的,例如,如果某個用戶程序訪問4G地址空間中的高位2G,那麼系統就會立即將其終止執行要注意的是,進程調用系統功能的時候,可以切換到內核模式執行,但是調用結束後,就返回到用戶模式了。

  用戶模式的進程總是被認爲是對操作系統穩定性的潛在威脅,所以它們的權限被嚴格地限制,任何觸及這些限制的舉動都將使進程被終止。
    而內核模式的組件則可以共享這些受保護的內核模式內存空間,在特權級別下運行(也稱爲Ring0),允許執行任何CPU指令,包括特權指令,可以無限制地訪問系統數據、代碼和硬件資源。
    內核模式代碼運行在系統地址空間中,並總是被認爲是可信任的,一旦被裝載運行後,驅動程序就是系統的一部分,可以無限制地做任何事情。

  總的來說,用戶模式程序被完全從操作系統隔離,這對操作系統的完整性來說是件好事情,但對某些種類的應用程序來說就太頭痛了,比如Debug工具。幸運地是,這些在用戶模式幾乎不可能完成的任務完全可以通過內核模式的驅動程序來完成,因爲這些驅動程序的操作是不受限制的。因此,如果你打算從用戶模式存取操作系統內部的數據結構或者函數的話,唯一的方法就是將一個內核模式驅動程序裝載到系統的地址空間中(並調用它),這是很簡單的事情,操作系統完全支持這樣的操作。


1.2 Windows NT設備驅動程序

1.2.1 設備驅動程序的分類

 

 Windows NT支持的設備驅動程序的範圍很廣,它們的分類如下:

    用戶模式的驅動程序:
◎ 虛擬設備驅動程序(Virtual Device Drivers/VDD)--用戶模式的組件,用於爲16位的MS-DOS應用程序提供虛擬的執行環境,雖然和Windows 95/98裏面的VxD從功能上看起來是差不多的,但實際上兩者根本不同。
◎ 打印驅動程序--將與設備無關的圖形轉換到和打印機相關的指令

    內核模式驅動程序:
◎ 文件系統驅動程序--實現標準的文件系統模型
◎ 傳統設備驅動程序--用於在沒有其他驅動程序幫助的情況下控制硬件設備,它們是爲老版本的Windows NT系統所寫的,但是也可以不加修改地運行在Windows 2000/XP/2003系統上
◎ 視頻驅動程序--不用多介紹了吧?
◎ 流驅動程序--支持多媒體設備,如聲卡
◎ WDM驅動程序--即Windows Driver Model,WDM包括對Windows NT電源管理和即插即用的支持,WDM可以在Windows 2000、Windows 98和Windows ME下實現,所以在這些操作系統下,WDM驅動程序在源代碼級別是兼容的,在有些情況下,在二進制代碼級別上也是兼容的

    在不同的資料中,對驅動程序的分類方法可能完全不同,但這並不是問題。
    從名稱理解,設備驅動程序是用於控制某個設備的,但這個"設備"並不一定指的是物理上存在的設備,它也可以是虛擬設備。
    從文件結構上講,設備驅動程序就是一個普普通通的PE格式文件,就像其他EXE或者DLL文件一樣。設備驅動程序是一個可裝載的內核模式模塊,一般以SYS爲擴展名。他們之間的不同點在於兩種的裝載方法是完全不同的。實際上,我們可以把設備驅動程序理解成一個內核模式的DLL,用於完成在用戶模式下所不能完成的功能,本質上的不同就在於我們無法直接存取設備驅動程序的代碼和數據(注:DLL的代碼和數據是可以被直接存取的,這方面的資料可以參考《Windows環境下32位彙編語言程序設計一書》中的DLL一章),唯一的存取方式是通過I/O管理器,它提供了簡單的驅動程序管理環境


    剛開始學習KMD的開發的時候,你可能感覺自己根本就是一個菜蟲(旁白:就是比菜鳥還低級,呵呵~~~),因爲你以前用Windows API開發程序的經驗在這裏根本幫不上忙,即使你以前寫過n多個(n趨向無窮大……)用戶模式下的應用系統也沒用。內核提供了完全不同的函數和數據結構,以至於你要從頭開始瞭解,而且資料奇缺無比,一般情況下,可供參考的只有頭文件。

 

1.2.2 分層的和單層的設備驅動程序

    大部分控制硬件設備的驅動程序是分層的驅動程序,分層驅動的概念就是當用戶模式發出一個請求時,每個請求從高層次的驅動程序逐層處理並流傳到低層次的驅動程序中,一個I/O請求的處理可能分步在多個驅動程序中,例如,如果一個應用程序發出讀盤請求,處理請求會在多個驅動程序中流過,在其中你也可以再加入n多個過濾驅動程序(比如插入一個加解密的模塊)。


    單層的驅動程序是最簡單的一類驅動程序,這一類驅動程序通常並不依賴於其他已裝載的驅動程序,他們的接口僅僅針對用戶模式的應用程序,開發和調試這一類驅動程序是非常簡單的,我們即將開始討論的就是這類程序,其他類型的驅動程序將在以後討論。

1.3 線程上下文(Thread Context)

    在大多數情況下,我們的系統中只安裝了一個CPU,所以,對於所有這些運行中的程序來說,操作系統對每個進程中的線程所使用的CPU時間進行調度,循環爲每個線程分配時間片,這就造成了多個程序同時執行的假象。如果系統中安裝了多個CPU,那麼操作系統的調度算法將複雜得多,因爲它要將各CPU上的線程進行平衡。如果Windows檢測到一個新線程要開始運行了,它將進行一次上下文切換(context switch)(注:上下文(Content)實際上就是線程運行的環境,也就是運行時各寄存器和其他東東的狀態,更自然的理解就是"線程狀態")。所謂上下文切換就是保存線程運行時的機器狀態,然後將另一個線程的狀態恢復並重新開始執行。如果重新開始執行的線程屬於另一個進程,那麼該進程的地址空間也將被同時切換過來(通過在CR3寄存器中裝入頁表)。
    每個用戶進程都有私有的地址空間,所以他們的頁表都是不同的,CPU通過切換頁表來將虛擬地址映射到物理地址,設備驅動程序並不需要直接做這些工作。上下文切換比較耗CPU時間,所以驅動程序一般不創建它們自己的線程,它們一般在下列環境中的一箇中運行:

1. 在發起I/O請求的用戶線程中運行
2. 在內核模式下的系統線程中運行
3. 作爲中斷運行(並不處於哪個特定的進程或線程中,因爲它們都被暫時掛起了)

    在處理I/O請求包(IRPs)時,我們總是運行在和用戶模式的調用者相同的進程上下文中運行,這樣我們就能對用戶程序的地址空間進行尋址。但是當驅動程序被加載或者卸載的時候,我們將在系統進程中運行,這時存取的只能是系統的地址空間。

 

1.7 彙編程序員使用的KmdKit

    KmdKit包含了所有用匯編開發KMD所需要的東西:include文件、lib文件、宏定義、例子文件、工具和一些文章,你可以自己在軟件包中找到更多的東西,下一節我們將從這個軟件包中包括的一些例子開始學習KMD的編程。

1.8 驅動程序的調試

    調試內核模式的代碼需要合適的調試器,Compuware的SoftIce是個不錯的選擇(見 http://www.compuware.com/products/numega/index.htm),當然你也可以使用Microsoft Kernel Debugger,它需要兩臺計算機:主機和目標機器,目標機器是被調試的機器,主機是運行調試軟件的機器。Mark Russinovich ( http://www.sysinternals.com/ ) 也寫了一個工具,叫做LiveKd,它允許在單臺機器上運行Microsoft Kernel Debugger,而不再需要兩臺機器了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章