2.1. 开发环境

我们使用VS2019 + WDK进行驱动开发,他们可以在Visual Studio Installer中进行安装

image-20211003165238474

2.2. 第一个驱动项目

安装完之后VS2019中选择WDM Empty Driver 模板。

image-20211003170238282

项目创建完成后有一个Sample.inf,本次Demo我们还不需要它先将它删除。在Source File中创建一个Sample.cpp文件,并写入以下代码:

#include <ntddk.h>

void SampleUnload(_In_ PDRIVER_OBJECT DriverObject) {

    KdPrint(("SampleUnload........."));
    UNREFERENCED_PARAMETER(DriverObject);
}

EXTERN_C
NTSTATUS 
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
) 
{
    UNREFERENCED_PARAMETER(RegistryPath);

    DriverObject->DriverUnload = SampleUnload;

    return STATUS_SUCCESS;
}

我们来较为详细的讲解一下这份代码,首先是#include <ntddk.h> 这个就和我们传统C语言程序的 #include <stdio.h> 引入头文件;DriverEntry类比与main函数,是驱动程序的入口;因为驱动程序执行在内核空间,如果发生内存泄露比在应用层的程序要麻烦的多,所以我们需要一个卸载函数供这个驱动函数在卸载的时候使用,在本例中SampleUnload就是承担这个角色,并在DriverEntry给DriverObject->DriverUnload赋值即可;关于UNREFERENCED_PARAMETER宏的使用是因为在驱动编程中警告等级是4 参数未使用会无法通过编译,使用这个宏可以达到“被引用”的效果;EXTERN_C是因为DriverEntry 函数必须具备C语言方式链接,而默认是以C++方式链接所以需要使用这个宏显示定义;KdPrint是一个宏它本质调用DbgPrint,可以类比成printf函数起到对外打印,用DbgView可以查看。

2.3. 部署驱动程序

在64位的操作系统中,在启动驱动程序的时候需要该驱动程序有对应的数字签名,或者将系统设置成测试签名模式才能正常运行,我们一般可以使用亚洲诚信对刚才生成的驱动程序进行签名。

image-20211003195103726

部署一个驱动程序一般进过四个阶段:安装服务 -> 启动 -> 停止 -> 移除服务,这个就对应传统驱动加载工具。

image-20211003195326353

我们可以调用CreateService创建服务或者使用sc.exe工具进行创建,可以在HKLM\System\CurrentControlSet\Services\ 看到我们创建的服务,sc start/stop sample 启动或停止程序。

image-20211003130607129

image-20211003130742960

2.4. 课后练习

image-20211003202712503

#include <ntddk.h>

void SampleUnload(_In_ PDRIVER_OBJECT DriverObject) {

    KdPrint(("SampleUnload........."));
    UNREFERENCED_PARAMETER(DriverObject);
}

EXTERN_C
NTSTATUS 
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
) 
{
    UNREFERENCED_PARAMETER(RegistryPath);

    DriverObject->DriverUnload = SampleUnload;

    RTL_OSVERSIONINFOW osvi;
    osvi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
    RtlGetVersion(&osvi);

    DbgPrint("RtlGetVersion");
    DbgPrint("The osvi.dwMajorVersion is: %u", osvi.dwMajorVersion);
    DbgPrint("The osvi.dwBuildNumber is: %u", osvi.dwBuildNumber);
    DbgPrint("The osvi.dwMinorVersion is: %u", osvi.dwMinorVersion);

    return STATUS_SUCCESS;
}

image-20211003135942451