教程:https://www.pnpon.com/article/detail-117.html
环境搭建教程:https://blog.csdn.net/blackwoodcliff/article/details/103838335
开发Windows驱动程序时,debug比较困难,并且程序容易导致系统崩溃,这时可以使用Virtual Box进行程序调试,用WinDbg在主机上进行调试。
需要使用的工具:
Virtual Box:用于安装虚拟机系统,用于运行待测试的驱动程序;
Windows WDK: 需要和windows版本、Visual Studio SDK版本和WDK版本要完全一致。
WinDbg preview:在微软应用商店安装;
OSR Driver Loader:用于加载待调试的Windows驱动程序,需要禁用虚拟机的数字签名(https://www.osronline.com/article.cfm%5earticle=157.htm)
配置虚拟机和WinDbg:
- 首先进入虚拟机系统中,以administrator模式执行cmd,
输入bcdedit /debug on以及bcdedit /dbgsettings serial debugport:1 baudrate:11520;
也可以通过界面来配置
- 配置虚拟机系统的com1口为管道和主机进行通信,接着关闭虚拟机系统。
在Virtual Box的Settings->Serial Ports设置Port:COM1, Port Mode: Host Pipe,取消勾选Connect to existing pipe/socket, Path/Address: \.\pipe\com1
- 启动主机的WinDbg程序
打开file->Kernel Debug->选择COM口,勾选Pipe,Reconnect, Port改为\.\pipe\com1
启动测试模式
- Windows开启测试模式
以管理员模式启动cmd,输入以下命令:
开启系统的测试模式 bcdedit /set testsigning on
开启操作系统内核调试 bcdedit /debug ON
开启应用程序调试 bcdedit /bootdebug ON
重启,重启后一般在电脑右下角会显示测试模式等字样,个人更偏向与使用此方式
- 启动禁用数字签名
以管理员模式运行cmd执行如下命令:
禁用签名 bcdedit.exe /set nointegritychecks on
恢复签名 bcdedit.exe /set nointegritychecks off
编写一个简单的Windows驱动程序:
编写之前需要配置一下项目的VS配置。
#include <ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
DbgPrint("goodbye!\n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) {
DbgPrint("Hello, haidragon\n");
pDriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
ddk驱动
#include <ntddk.h>
#define DEVICE_NAME L"\\device\\ddk_device"
#define LINK_NAME L"\\??\\ddk_device_link"
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchRead(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING uLinkName = { 0 };
RtlInitUnicodeString(&uLinkName, LINK_NAME);
IoDeleteSymbolicLink(&uLinkName);
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("Driver unloaded ddk_device\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegPath)
{
UNICODE_STRING uDeviceName = { 0 };
UNICODE_STRING uLinkName = { 0 };
NTSTATUS ntStatus = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
ULONG i = 0;
DbgPrint("Driver load ddk_device\n");
RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
RtlInitUnicodeString(&uLinkName, LINK_NAME);
ntStatus = IoCreateDevice(pDriverObject,
0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("IoCreateDevice failed:%x", ntStatus);
return ntStatus;
}
pDeviceObject->Flags |= DO_BUFFERED_IO;
ntStatus = IoCreateSymbolicLink(&uLinkName, &uDeviceName);
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice(pDeviceObject);
DbgPrint("IoCreateSymbolicLink failed:%x\n", ntStatus);
return ntStatus;
}
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
{
pDriverObject->MajorFunction[i] = DispatchCommon;
}
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClean;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObject->DriverUnload = DriverUnload;
DbgPrint("Driver load ok!\n");
return STATUS_SUCCESS;
}
驱动安装和测试
使用OSR Driver Loader安装驱动和测试
使用dbgview工具查看驱动打印的日志,配置如下: