內核第三講,進入ring0,以及編寫第一個內核驅動程序.


       內核第三講,進入ring0,以及編寫第一個內核驅動程序.

PS: 請下配置雙機調試,下方有可能用到.如果不配置,則你可以不用調試, 博客連接: http://www.cnblogs.com/iBinary/p/8260969.html

一丶進入ring0之前的簡介

進入0環之前,我們要明白操作系統的設計,操作系統允許驅動程序使用In out等等特權指令來操作高2G的內存.那么必然會有接口.

圖示如下.

那么我們可以模擬一個驅動程序來進入0環.

而操作系統提供的接口的,有專門的名稱. 叫做DDK, 現在改名為WDK了.

DDK: Driver Development Kit  驅動程序開發包,例如我們寫的3環系統下,用到的SDK,也可以成為是API.只不過現在叫做內核方法(內核函數)了.

WDK:Windows Driver Kit 

WDK是DDK升級而來的.操作系統為了支持熱插拔,所以對DDK升級了.熱插拔就是U盤插入系統.不用安裝驅動了.和U盤綁定在一起了.

 

WDK官方下載連接: https://developer.microsoft.com/zh-cn/windows/hardware/windows-driver-kit

我自己用的是WDK7.1.7600,會上傳到課堂資料中.有興趣的可以下載.

注意: 如果編寫驅動程序,請下載對應系統的WDK,因為驅動程序不兼容.只會跟着系統走.

二丶WDK的安裝.

下載之后直接下一步,下一步即可. 如果不會建議百度.

 

 

三丶進入0環,編寫第一個內核驅動程序

在進入ring0之前,我們要知道,不管是驅動程序,或者是應用程序,都會有一個入口點.

比如控制台的入口點是 main,窗口的是winmain.那么看下驅動程序的入口點是什么.

PS:安裝好WDK之后,會有幫助文檔.可以參考幫助文檔.

如果我們要編寫內核驅動,則要看內核驅動的入口點,也就是kerner mode,內核模型.

如果是編寫硬件驅動,則尋找WDM即可.

 

NTSTATUS 
  DriverEntry(         //驅動的入口點
    __in struct _DRIVER_OBJECT  *DriverObject,
    __in PUNICODE_STRING  RegistryPath 
    )
  {...} 

返回值: STATUS_SUCCESS

內核輸出的API

ULONG
  DbgPrint(
    IN PCHAR  Format,
    . . . .  [arguments] 
    );

利用入口我們可以簡單編寫一個內核驅動了.

驅動我們可以用C語言去寫.也可以是C++

 

#include <Ntddk.h> //編寫內核驅動需要包含NTddk頭文件.

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT  *DriverObject,
                      __in PUNICODE_STRING  RegistryPath)
{
    int i = 0;
    DbgPrint("HelloWorld, %p\r\n",&i);
    
    return STATUS_SUCCESS;
}

在編譯驅動程序的是否,我們需要一個sources  文件

格式:

TARGETNAME= MyFirstDrive          //指明編譯的文件名 
TARGETTYPE=DRIVER                 //指明編譯的類型
SOURCES= MyFirstDrive.c            //指明編譯的文件

圖示:

 

 編譯的時候找我們的開發包.

通過開始程序,找到我們的開發包中的編譯XP命令框.點開.

輸入編譯命令 build 文件名

回車就可以編譯我們的驅動程序了.

成功會生成一個sys后綴的文件.那么我們就可使用了.

四丶雙機調試,加載我們的驅動.

我們以調試系統啟動.然后使用加載驅動的工具,加載我們的驅動,那么就可以在調試器中看到我們的驅動代碼了.

當我們啟動之后,我們可以查看下調試器,可以調試我們的代碼.

請注意我們打印的地址,地址是高2G的空間.所以我們就進入了0環空間了.

五丶編寫驅動卸載功能.

我們的驅動現在可以加載.啟動.停止.但是不能卸載.原因就是我們沒有寫卸載的函數.

比如我們的DLL,  DLL來的是否還分為4中情況.

很簡單.只需要把我們的驅動代碼改變一下即可.

#include <Ntddk.h> //編寫內核驅動需要包含NTddk頭文件.


//卸載回調函數
VOID Unload(__in struct _DRIVER_OBJECT  *DriverObject)
{
  DbgPrint("Unload MyDrive\n");
}

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT  *DriverObject,
                      __in PUNICODE_STRING  RegistryPath)
{
    int i = 0;
    DbgPrint("HelloWorld, %p\r\n",&i);
    
    //注冊一下驅動卸載的函數
    DriverObject->DriverUnload = Unload;

    return STATUS_SUCCESS;
}

給個卸載的函數指針即可.注意啟動入口點的參數是一個結構體.啟動你想要支持卸載驅動.那么就寫上卸載驅動的函數指針即可.

六丶藍屏的出現.

編寫驅動代碼,不像我們編寫ring3下的應用程序,崩潰了就是崩潰了. 我們寫驅動程序恨不得寫一行,檢查500行.

看下藍屏的實現.只要我們的程序異常,那么就會藍屏.

代碼:

#include <Ntddk.h> //編寫內核驅動需要包含NTddk頭文件.


//卸載回調函數
VOID Unload(__in struct _DRIVER_OBJECT  *DriverObject)
{
  DbgPrint("Unload MyDrive\n");
}

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT  *DriverObject,
                      __in PUNICODE_STRING  RegistryPath)
{
    int i = 0;
     int *p = NULL;   //異常代碼.會造成C05訪問異常.
    DbgPrint("HelloWorld, %p\r\n",&i);
    
   
    *p = 1;       //代碼會產生異常,系統會藍屏.

    //注冊一下驅動卸載的函數
    DriverObject->DriverUnload = Unload;

    return STATUS_SUCCESS;
}

 

很簡單,就加了一行C05訪問異常的代碼.

重新編譯一下.並且驅動加載.

因為家里電腦系統原因,藍屏了會緊接着重啟.所以來不及截圖.請大家自己嘗試.

課堂代碼資料:   

內核工具下載: 鏈接:https://pan.baidu.com/s/1o9PjpUU 密碼:k5sp

課堂驅動代碼資料下載: 鏈接:https://pan.baidu.com/s/1kXiSluv 密碼:jnov

 

轉載請著名出處,謝謝.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM