来记录一下自己学习驱动开发的过程,便于复习回忆。
环境:Windows10 Visual Studio 2019 WDK1803 VMware16 Windows1804
工具:DebugView 数字签名工具(signtools-v3.2)
VMware安装1804的系统,使用签名工具避免开启免签,个人感觉安全些。
类似Windows应用程序有统一的WinMain入口函数,内核驱动也有一个统一的入口函数,DriverEntry
NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
第一个参数代表驱动对象指针,操作系统在内存中为当前驱动分配了一个类型为DRIVER_OBJECT的数据结构,用于记录该驱动的详细信息。
第二个参数代表当前驱动对应的注册表位置,类型为UNICODE_STRING
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
其中Buffer为一个指针,指向一个UNICODE类型的字符串缓冲区;
MaximumLength表示Buffer所指向缓冲区的总空间大小,一般等于Buffer被分配时的内存大小,单位为字节;
Length表示Buffer所指向缓冲区中字符串的长度,单位也是字节。
驱动SYS文件需要运行,首先需要把这个驱动文件创建成一个服务(第三方服务,区别于系统服务),
注册成功后,系统会把该服务信息写入到注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Service 下,以服务名作为一个注册表的键名。
如下图所示:
下面展示一个最简单的驱动程序:
#include "ntddk.h" //这个是内核开发所需的头文件ntddk.h
VOID DriverUnload( PDRIVER_OBJECT DriverObject )//这个函数很重要,但不一定需要,没有运行后就无法停止
{
if ( DriverObject != NULL )
{
DbgPrint("[%ws] Driver Upload,Driver Object Address:%p", __FUNCTIONW__,DriverObject);
}
return;
}
NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject , PUNICODE_STRING RegistryPath ) //驱动入口函数
{
//KdBreakPoint();//断点,调试时使用
DbgPrint("[%ws] Hello Kernel World\n",__FUNCTIONW__); //打印日志,WDK提供的API,与其类似的是KdPrint函数(只对DeBug版本的驱动有效)
// %ws 表示打印一个以'\0'结束的UNICODE字符串 , FUNCTIONW表示当前函数名字,对应 %ws
if ( RegistryPath != NULL )// 判断是否为NULL ,注册表路径是否存在
{
DbgPrint("[%ws] Driver Object Address:%p\n", __FUNCTIONW__,DriverObject);
DriverObject->DriverUnload = DriverUnload;//调用DriverUnload函数,内核驱动停止
// A B C
// B为A的一个函数指针 ,
}
return STATUS_SUCCESS;//返回STATUS_SUCCESS表示成功,否则失败
}
UNICODE %ws
UNICODE_STRING %wZ
编译上述驱动
方式多种,直接使用VS编译,
期间存在一些问题,记录一下:
生成空驱动项目后,需要把自动生成的sys移除(不是删除),再重新编译
驱动的运行与调试
生成的sys都通过驱动签名软件进行签名避免关闭系统的驱动校验,
注册驱动的命令
.\sc.exe create driver1 binPath="C:\driver\driver1.sys" type= kernel start= demand
这个稍微记一下,类型为内核,启动方式为手动
其他命令如运行、停止、删除都是sc + start\stop\delete + DriverName
驱动运行时可以管理员运行Dbgview查看DbfPrint的日志
内核驱动不支持暂停操作
一下程序可以注册驱动:
aaa
驱动的调试在虚拟机上进行,
bcdedit /debug on 开启调试模式
bcdedit /dbgsetting net hostip:xxx.xxx.xxx.xxx port:50001 通过网络进行调试
KdBreakPoint与DbgBreakPoint的区别与DbgPrint和KdPrint一样