FISH 的专栏

天生我才必有用

kernel Driver Dll 内核模式 DLL编写

内核DLL编写

导出驱动程序缺少很多完整内核模式驱动应该有的特征。
(1) 可以为 IRP 处理提供支持例程, 但它不接收 IRP, 所以它不包含派遣例程.
(2) 不存在设备堆栈中
(3) 在服务控制管理器中没有入口点函数(不作为系统服务)
(4) 它确实有 DriverEntry 例程, 但仅仅是为了使代码能编译通过而已, 不被调用
    (注: 程序编译时 bufferoverflowk.lib 中的 GsDriverEntry 例程引用了我们当前项目中的 DirverEntry        例程, 所以如果不定义 DirverEntry, 程序不能通过。 类似于 MSVCRTD.lib 中的 __tmainCRTStartup 引用了 main, 如果我们在C语言中把 main 给去掉了,结果同样是不能编译通过 )


标准驱动程序也可以作为导出驱动程序使用, 不过该驱动程序必须用导出驱动的方法 build, 按照标准驱动程序的方法加载.


构建方法:

(1) 给 TARGETTYPE 赋值为 EXPORT_DRIVER

 TARGETTYPE = EXPORT_DRIVER

(2) 可以使用 DLLDEF 宏指定导出模块定义文件

     DLLDEF="c:/export_drv_test/driver.def"
     导出模块列表为编译器和连接器提供了导出例程信息.

(3) 在导出函数前面加 DECLSPEC_EXPORT

(4) 编译后 生成文件 Export*.lib 和 Export*.sys 文件


导入函数:
在导入函数的前面加上 DECLSPEC_IMPORT.


导出驱动程序必须安装在 %SystemRoot%/system32/drivers 目录中.在 windows NT 4.0中, 导出驱动程序一旦被加载则只有在系统关闭时才被卸载. Windows 2000 以后, 系统保存着一个引用计数, 这个引用计数表示导出驱动程序的函数被其他驱动函数导入的次数。当每个导入了函数的驱动程序被卸载时OS 就减少引用计数。 如果引用计数为0, OS 卸载导出驱动程序.


导出驱动程序必须包含标准的入口点例程 DllInitialize 和卸载例程 DllUnload. 否则引用计数的机制不会起作用. 没有这 2 个例程导出驱动程序一但被加载则只有在系统关闭时才能卸载.


上面的信息参考了 DDK, 参考下面代码和注释,可以发现上面某些信息不太准确.

导出驱动程序例子源码:

/*================================================================================

KernelDLL.cpp

================================================================================*/

/**************************************************************************************************/     
/*                                                                                                */ 
/*                                                                                                */     
/* Notes:                                                                                         */
/*        1) It is not strictly necessary for the executable to be located under the directory    */     
/*           %systemroot%/system32/drivers.  It will work if the executable is located in the     */     
/*           same place as that for the driver that causes the DLL to be loaded.  Neither is the  */     
/*           DLLDEF statement necessary in the soources file.                                     */     
/*                                                                                                */     
/*        2) This kernel DLL will be loaded automagically by the OS when the first driver         */     
/*           importing from this DLL is about to be loaded.  The DLL will be unloaded by the OS   */     
/*           when the last importing driver has been unloaded.                                    */     
/*                                                                                                */     
/*        3) For unloading to be done, both DllInitialize() and DllUnload() must be present and   */     
/*           defined in KernelDLLRtns.def.                                                        */
/*                                                                                                */     
/**************************************************************************************************/     
                                                                                               
#ifdef __cplusplus  // C++ conversion.                                                         
extern "C"                                                                                     
{                                                                                              
#endif              // End #ifdef C++ conversion.                                              
                                                                                               
#include <ntddk.h>
                                                                                               
#ifdef __cplusplus  // C++ conversion.                                                         
}                                                                                              
#endif              // End #ifdef C++ conversion.                                              

//***************************************************************************//
//                                                                           //
// Routine prototypes.                                                       //
//                                                                           //
//***************************************************************************//


/**************************************************************************************************/
/*                                                                                                */
/* DriverEntry                                                                                    */
/*                                                                                                */
/* Notes:                                                                                         */
/*        1) DriverEntry() is required for linking but is never invoked.  DllInitialize() and     */
/*           DllUnload() instead are invoked when the DLL is loaded and unloaded, respectively.   */
/*                                                                                                */
/**************************************************************************************************/
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING)
{
 return STATUS_SUCCESS;
}


/**************************************************************************************************/
/*                                                                                                */
/* Test routine that will be imported and invoked by CallKernelDLL.sys.                           */
/*                                                                                                */
/**************************************************************************************************/
__declspec(dllexport) NTSTATUS KernelDLLRtnsTest( PDEVICE_OBJECT pDevObj )
{
 NTSTATUS                status = STATUS_SUCCESS;

 DbgPrint(("ExportFun is Called!  KernelDLLRtnsTest()/n"));

 return status;
}


/**************************************************************************************************/
/*                                                                                                */
/* Routine that is invoked when the DLL is loaded.                                                */
/*                                                                                                */
/* Notes:                                                                                         */
/*        1) Support for this routine appeared in Win2K.                                          */
/*        2) The presence of DllInitialize() and DllUnload() allows the DLL to be unloaded.       */
/*                                                                                                */
/**************************************************************************************************/
extern "C" NTSTATUS  DllInitialize( PUNICODE_STRING pRegistryPath )
{
 NTSTATUS                status = STATUS_SUCCESS;

 /* COMMONLY INITIALIZE RESOURCES REQUIRED BY OTHER ROUTINES */

 DbgPrint(("DllInitialize() is CALLED /n"));

 return status;
}


/**************************************************************************************************/
/*                                                                                                */
/* Routine that is invoked when the DLL is unloaded.                                              */
/*                                                                                                */
/* Notes:                                                                                         */
/*        1) Support for this routine appeared in Win2K.                                          */
/*        2) The presence of DllInitialize() and DllUnload() allows the DLL to be unloaded.       */
/*                                                                                                */
/**************************************************************************************************/
extern "C" NTSTATUS  DllUnload() 
{
 NTSTATUS                status = STATUS_SUCCESS;

 DbgPrint(("DllUnload() is CALLED/n"));

 return status;
}


/*================================================================================

Sources

================================================================================*/
TARGETNAME=KernelDLL
#TARGETPATH=../lib$(BUILD_ALT_DIR)
TARGETPATH=lib
TARGETTYPE=EXPORT_DRIVER         # SET TYPE OF DRIVER: EXPORT FUNCS
DLLDEF="KernelDLLRtns.def"       # IT IS NOT NECCESOORY TO HAVE THIS STATEMENT. BY DEFAULT, DEL FILE IS  "KernelDLL.def" .

USER_C_FLAGS=$(USER_C_FLAGS) /FAsc

# pick up definitions from external environment

C_DEFINES=$(C_DEFINES)

#
# set up Visual C++ source browsing
#
BROWSER_INFO=1
BROWSERFILE=$(TARGETNAME).bsc -n

INCLUDES=$(BASEDIR)/inc/ddk/wxp

SOURCES=                    /
        KernelDLL.cpp       /

/*================================================================================

KernelDLL.def

================================================================================*/
NAME KernelDLL.sys

EXPORTS

; They act to ensure that these 2 routines are known to the OS, with the result that the kernel DLL can be unloaded.

  DllInitialize private
  DllUnload     private


/*================================================================================

makefile

================================================================================*/
!INCLUDE $(NTMAKEENV)/makefile.def

 

阅读更多
个人分类: windows kernel
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭