[原创]使用GCC创建 Windows NT 下的内核DLL

原文链接:使用GCC创建 Windows NT 下的内核DLL

 

     在温习<<Windows 2000 Driving>>分层驱动程序一章的时候,看到了关于紧耦合驱动连接方式,这种方式不依赖于I/O管理器的串联,而是直接调用内核例程,这样可以大大的提高驱动的执行效率。

     为了实现这样一种功能,必须提供一种类似于在用户模式中DLL的机制,只不过该"DLL"是加载到内核中的。其实Windows NT 内核本身早就利用了这样机制,比如Hal.dll、ntoskrnl.exe和某些类驱动程序等,他们分别为第3方驱动程序导出了HAL层、内核层、执行体层的功能函数。

      在 Tim Roberts 的 《内核模式的 DLL》一文中,给出了内核DLL的主要特征:

 

    内核 DLL 就像用户模式 DLL 一样:链接器在构建 DLL 时生成一个导入库,然后将此库包含到将要使用此DLL 的任何驱动程序的目标库列表中。既不需要注册表技巧,也不需要任何特别的动作来起停该 DLL。内核 DLL将随任何引用之的其他驱动程序自动加载,而随最后一个引用之的驱动程序自动卸载(注 1)。

 

      为了实现这样一个DLL,Roberts给出的做法是使用DDK来生成一个TARGETTYPE为EXPORT_DRIVER的项目。我试了一下,如其所愿,的确建立一个xxx.sys文件,我还观察了一下该sys的PE类型,发现它与标准的内核sys并无两样,那么能不能用gcc来生成一个内核模式的DLL呢?答案是肯定的!如果你正在用gcc(MinGW)在写Windows NT 下的Core Dll的话,那么也可以写出DDK中EXPORT_DRIVER类型的模块了,具体做法从略...

 

  好了,上面只是开个玩笑,呵呵。下面就详细说说如何用MinGW来写一个CoreDll:

  1. 首先在你的系统中应该安装一个MinGW,我现在用的是(MinGW 5.1.4);
  2. 在你的系统中还要有一个Masm32V9.0+的环境(这个不是必须的,Gcc也有能力自己生成驱动程序文件,而我采用的是Masm方式),你也可以安装WINDDK,用它的环境生成最终的的驱动文件。
  3. 用gccNTDrvFrame(注2)建立一个新的驱动包,其中如果要想实现CoreDll动态加载和卸载功能必须在sys.c中提供以下2个例程,你可以将构造和析构的相关内容放在它们里面。你同样要提供一个Driver 必须包含标准的 DriverEntry 入口点,不过实际上系统不会调用它。这个需求是创建系统的人为限制,因为它会为每个内核驱动程序把 /ENTRY:DriverEntry 添加到链接器选项中。因此我们为只导出的 DLL 也必须提供一个伪入口点。 
1 __declspec(dllexport) DDKAPI NTSTATUS DllInitialize(/
2         IN PUNICODE_STRING RegistryPath);
3 __declspec(dllexport) DDKAPI NTSTATUS DllUnload(void);

     4.  建立一个需要导出的函数,我这里只是示例一下,所以写了一个简单的导出函数: 

 1 __declspec(dllexport) DDKAPI NTSTATUS GetMagicNum(IN int *pVal)
 2 {
 3     if(!pVal)
 4     {
 5         DbgPrint("err : pVal == NULL!/n");
 6         return STATUS_DEVICE_CONFIGURATION_ERROR;
 7     }
 8     DbgPrint("*pVal is %d/n",*pVal);
 9     *pVal *= 11 * 11;
10     DbgPrint("After OP --- *pVal is %d/n",*pVal);
11     return STATUS_SUCCESS

    5. 为连接器建立def文件,内容如下:

NAME CoreDll.sys
EXPORTS
    DllInitialize PRIVATE
    DllUnload PRIVATE
    GetMagicNum

     6. 运行gccNTDrvFrame的builder,完成CoreDll的编译和连接,如果没有错误将会生成若干个文件,其中只会用到2个:一个是xxx.sys,这个不用说就是供其它驱动调用的CoreDll,另一个是xxx.lib,它是所有需要调用xxx.sys的其它驱动程序建立时需要的文件,它和hal.lib、ntoskrnl.lib完全一样。

 

    7. 新建另一个Driver工程,在b.bat中的link连接选项中添加xxx.lib。声明和调用外部函数的方法如下:

__declspec(dllimport) DDKAPI NTSTATUS GetMagicNum(IN int *pVal);
DDKAPI NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,/
    PUNICODE_STRING pRegistryPath)
{    
    PDEVICE_OBJECT pDevObj;
    NTSTATUS status = STATUS_DEVICE_CONFIGURATION_ERROR;
    
    PRINT("[%s]enter DriverEntry.../n",__func__);
    
    RtlInitUnicodeString(&DevName,DEVNAMEW);
    RtlInitUnicodeString(&SymlnkName,SYMLNKNAMEW);
    
    if(IoCreateDevice(pDriverObject,0,&DevName,FILE_DEVICE_UNKNOWN,/
        0,false,&pDevObj) != STATUS_SUCCESS)
    {
        PRINT("[%s]IoCreateDevice Failed!/n",__func__);
        goto QUIT;
    }
    
    if(IoCreateSymbolicLink(&SymlnkName,&DevName) != STATUS_SUCCESS)
    {
        IoDeleteDevice(pDevObj);
        PRINT("[%s]IoCreateSymbolicLink Failed!/n",/
            __func__);
        goto QUIT;
    }
    
    pDevObj->Flags |= DO_BUFFERED_IO;
        
    pDriverObject->DriverUnload = DriverUnload;
    pDriverObject->MajorFunction[IRP_MJ_CREATE] = /
        DrvDispatchCreateClose;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = /
        DrvDispatchCreateClose;
    pDriverObject->MajorFunction[IRP_MJ_READ] = /
        DispatchRead;
    pDriverObject->MajorFunction[IRP_MJ_WRITE] = /
        DispatchWrite;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = /
        DrvDispatchControl;
    pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = /
        DrvShutdown;
    if(!NT_SUCCESS(IoRegisterShutdownNotification(/
        pDriverObject->DeviceObject)))
    {
        PRINT("[%s]err : Register Shutdown Failed!/n",/
            __func__);
    }
    
    int i = 11;
    GetMagicNum(&i);
        
    PRINT("[%s]Addr of KeServiceDescriptorTable : %p/n",/
        __func__,KeServiceDescriptorTable);
    PRINT("[%s]leave DriverEntry.../n",__func__);
    
    status = STATUS_SUCCESS;
QUIT:
    return status;
}

你当然不一定非要在DriverEntry中调用,因为xxx.sys由系统在调用sys之前自动动态加载.

 

         8. 用builder建立这个sys,然后整个过程结束了。

 

   结束语:这里只是一个最简单的示例,如果是只干这样的"小"事而用CoreDll的话,未免杀鸡用牛刀的意思。CoreDll的用途可以被极大的拓展,至于如何发挥您的激情与才干,就不是我力所能及的了。(^o^)

 

注1 :不过,在 Windows 98 第二版或者 Windows Me 中内核 DLL 永远也不会卸载。

注2 gccNTDrvFrame是我写的一个gcc建立windows NT 驱动的框架包,稍后会在新文章中介绍。

 

(PS : 文章参考http://sluttery.spaces.live.com/blog/cns!3569FEA80C717FD4!519.entry

转载于:https://www.cnblogs.com/hopy/p/3829013.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值