配置好环境先写一个hello world来测试一下。

#include <ntddk.h>

NTSTATUS unload(PDRIVER_OBJECT driver)
{
    DbgPrint("Driver unload success..");
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) 
{
    driver->DriverUnload = unload;
    DbgPrint("Hello World\n");
    return STATUS_SUCCESS;
}

构成

驱动程序格式还是挺简单的,基本上有两个必要的模块组成。

  • unload
  • DriverEntry

DriverEntry

相当于main函数,驱动程序的载入函数,一般包含两个参数

PDRIVER_OBJECT driver    // 刚被初始化的驱动对象指针
PUNICODE_STRING reg_path    // 驱动在注册表中的键值
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) 
{
    driver->DriverUnload = unload;    // 注册卸载函数,位置无所谓。
    DbgPrint("Hello World\n");    // 方便查看运行状态。
    return STATUS_SUCCESS;    // 和return 0没啥区别。
}

DRIVER_OBJECT 结构体

这是驱动载入和退出函数的第一个参数,包含了一个驱动的详细信息。在wdn.h中可以得到定义

typedef struct _DRIVER_OBJECT {
    CSHORT Type;    //驱动类型
    CSHORT Size;    //驱动大小

    //
    // The following links all of the devices created by a single driver
    // together on a list, and the Flags word provides an extensible flag
    // location for driver objects.
    //

    PDEVICE_OBJECT DeviceObject;
    ULONG Flags;

    //
    // The following section describes where the driver is loaded.  The count
    // field is used to count the number of times the driver has had its
    // registered reinitialization routine invoked.
    //

    PVOID DriverStart;
    ULONG DriverSize;
    PVOID DriverSection;    //指向驱动程序映像的内存区对象
    PDRIVER_EXTENSION DriverExtension;

    //
    // The driver name field is used by the error log thread
    // determine the name of the driver that an I/O request is/was bound.
    //

    UNICODE_STRING DriverName;    //驱动名称

    //
    // The following section is for registry support.  This is a pointer
    // to the path to the hardware information in the registry
    //

    PUNICODE_STRING HardwareDatabase;

    //
    // The following section contains the optional pointer to an array of
    // alternate entry points to a driver for "fast I/O" support.  Fast I/O
    // is performed by invoking the driver routine directly with separate
    // parameters, rather than using the standard IRP call mechanism.  Note
    // that these functions may only be used for synchronous I/O, and when
    // the file is cached.
    //

    PFAST_IO_DISPATCH FastIoDispatch;

    //
    // The following section describes the entry points to this particular
    // driver.  Note that the major function dispatch table must be the last
    // field in the object so that it remains extensible.
    //

    PDRIVER_INITIALIZE DriverInit;
    PDRIVER_STARTIO DriverStartIo;
    PDRIVER_UNLOAD DriverUnload;    //驱动的卸载地址
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
  • Type:该字段标识该结构体的类型,始终设置DRIVER_OBJECT_TYPE
  • Size:该字段表示该结构体的大小,以字节为单位
  • DeviceObject:该字段是一个指针,指向驱动程序所创建的设备对象链表的头部。每个设备对象代表着一个设备或者驱动程序创建的一种虚拟设备
  • DriverStart:该字段是一个指针,指向驱动程序代码的入口点,也就是驱动程序的DriverEntry函数。该函数会在驱动程序被加载时被调用。
  • DriverSize:该字段表示驱动程序代码的大小,以字节为单位。

可以利用DriverSection来遍历当前系统下所有的驱动程序的具体信息。

UNICODE_STRING 结构体

在ntdef.h文件中可以看到定义

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
#ifdef MIDL_PASS
    [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
    _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH   Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;

卸载函数

驱动程序需要自定义一个卸载程序,因为系统为了稳定,驱动不会被系统自动卸载,所以需要手动去定义一下。

假如在DriverEntry中添加了某些系统回调,没有DriverUnload,系统就不知道什么时候该移除这些回调,如果暴力移除驱动,此时系统回调会出问题,系统回调表中存在了一个被移除掉的驱动的回调,当调用时系统蓝屏 。

NTSTATUS unload(PDRIVER_OBJECT driver)
{
    DbgPrint("Driver unload success..");
    return STATUS_SUCCESS;
}

其实也没有什么特殊操作,就告诉系统有这么一回事就行了,这里留个字符串来显示一下状态。

没有版权,随便复制,免费的知识应该共享 all right reserved,powered by Gitbook该文章修订时间: 2023-08-25 14:48:35

results matching ""

    No results matching ""