开始内核开发
2.1. 开发环境
我们使用VS2019 + WDK进行驱动开发,他们可以在Visual Studio Installer中进行安装
2.2. 第一个驱动项目
安装完之后VS2019中选择WDM Empty Driver 模板。
项目创建完成后有一个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位的操作系统中,在启动驱动程序的时候需要该驱动程序有对应的数字签名,或者将系统设置成测试签名模式才能正常运行,我们一般可以使用亚洲诚信对刚才生成的驱动程序进行签名。
部署一个驱动程序一般进过四个阶段:安装服务 -> 启动 -> 停止 -> 移除服务,这个就对应传统驱动加载工具。
我们可以调用CreateService创建服务或者使用sc.exe工具进行创建,可以在HKLM\System\CurrentControlSet\Services\ 看到我们创建的服务,sc start/stop sample 启动或停止程序。
2.4. 课后练习
#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;
}