windows 驱动与内核调试 学习2
Posted 不会写代码的丝丽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了windows 驱动与内核调试 学习2相关的知识,希望对你有一定的参考价值。
前言
我们知道我们驱动存在的意义往往是用于驱动硬件,而一个硬件读写大多数操作系统都是为文件io。既然是文件那么必然涉及到文件打开,读写等。我们看看在内核驱动该如何实现这些逻辑操作。
//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
_In_ struct _DRIVER_OBJECT* DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
//如果你没有用到参数需要告诉系统。
UNREFERENCED_PARAMETER(RegistryPath);
//打印信息
DbgPrint("hello drive loaded");
//触发一个断点
//DbgBreakPoint();
//驱动卸载回调注册
DriverObject->DriverUnload = myUnload;
//设置一个驱动映射的文件名称,RtlInitUnicodeString是一个便捷创建内核UNICODE_STRING函数
UNICODE_STRING ustrDevName;
//使用工具函数创建一个名叫MytestDriver驱动文件
RtlInitUnicodeString(&ustrDevName, L"\\\\Device\\\\MytestDriver");
//用于保存创建结果
PDEVICE_OBJECT pDevObj = NULL;
//IoCreateDevice用于创建一个DEVICE_OBJECT对象
auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);
if (NT_SUCCESS(ret))
//
DbgPrint("IoCreateDevice 成功 %p\\r\\n", ret);
else
DbgPrint("IoCreateDevice 失败\\r\\n");
return STATUS_FAIL_CHECK;
//这里便是注册驱动文件读写相关回调
//注册一个创建文件回调
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
//注册文件关闭
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
//读取
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
//写入
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
//控制相关 其实也可以使用写入代替 但是为了职责分明额外多一个回调
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
return STATUS_SUCCESS;
当函数卸载的时候一定要记得删除驱动文件哦
//这个函数被注册用于驱动卸载调用
VOID myUnload(
struct _DRIVER_OBJECT* DriverObject
)
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("hello drive unloaded");
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
if (DriverObject->DeviceObject !=NULL)
DbgPrint("驱动文件不为空执行删除");
IoDeleteDevice(DeviceObject);
我们贴出完成相关代码
#include <Ntddk.h>
//这个函数被注册用于驱动卸载调用
VOID myUnload(
struct _DRIVER_OBJECT* DriverObject
)
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("hello drive unloaded");
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
if (DriverObject->DeviceObject !=NULL)
DbgPrint("驱动文件不为空执行删除");
IoDeleteDevice(DeviceObject);
NTSTATUS
DispatchCreate(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
NTSTATUS
DispatchClose(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
NTSTATUS
DispatchRead(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
NTSTATUS
DispatchWrite(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
NTSTATUS
DispatchControl(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
_In_ struct _DRIVER_OBJECT* DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
//如果你没有用到参数需要告诉系统。
UNREFERENCED_PARAMETER(RegistryPath);
//打印信息
DbgPrint("hello drive loaded");
//触发一个断点
//DbgBreakPoint();
//驱动卸载回调注册
DriverObject->DriverUnload = myUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
UNICODE_STRING ustrDevName;
RtlInitUnicodeString(&ustrDevName, L"\\\\Device\\\\MytestDriver");
PDEVICE_OBJECT pDevObj = NULL;
auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateDevice 成功 %p\\r\\n", ret);
else
DbgPrint("IoCreateDevice 失败\\r\\n");
return STATUS_FAIL_CHECK;
return STATUS_SUCCESS;
我们利用工具将驱动文件进行加载
然后我们在利用winobj查看我们注册驱动文件
我们最后执行卸载操作。
上面的注册驱动文件不能在ring3 进行文件读写,如果你期望ring3也可以驱动需要额外注册一个另一个映射名(符号链接 )
相关代码如下
UNICODE_STRING symbolDevName;
RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateSymbolicLink 成功 \\r\\n");
else
DbgPrint("IoCreateSymbolicLink 失败%d\\r\\n", ret);
IoDeleteDevice(pDevObj);
return STATUS_FAIL_CHECK;
同样我们加载驱动
再卸载的时候同样记得要删除。
#include <Ntddk.h>
//这个函数被注册用于驱动卸载调用
VOID myUnload(
struct _DRIVER_OBJECT* DriverObject
)
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("hello drive unloaded");
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
if (DriverObject->DeviceObject != NULL)
DbgPrint("驱动文件不为空执行删除");
IoDeleteDevice(DeviceObject);
UNICODE_STRING symbolDevName;
RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
IoDeleteSymbolicLink(&symbolDevName);
//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
_In_ struct _DRIVER_OBJECT* DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
//如果你没有用到参数需要告诉系统。
UNREFERENCED_PARAMETER(RegistryPath);
//打印信息
DbgPrint("hello drive loaded");
//触发一个断点
//DbgBreakPoint();
//驱动卸载回调注册
DriverObject->DriverUnload = myUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
UNICODE_STRING ustrDevName;
RtlInitUnicodeString(&ustrDevName, L"\\\\Device\\\\MytestDriver");
PDEVICE_OBJECT pDevObj = NULL;
auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateDevice 成功 \\r\\n");
else
DbgPrint("IoCreateDevice 失败 %d\\r\\n", ret);
return STATUS_FAIL_CHECK;
UNICODE_STRING symbolDevName;
RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateSymbolicLink 成功 \\r\\n");
else
DbgPrint("IoCreateSymbolicLink 失败%d\\r\\n", ret);
IoDeleteDevice(pDevObj);
return STATUS_FAIL_CHECK;
return STATUS_SUCCESS;
微软IRP设计
以下来自微软官方的一个设计架构图
具体可参阅
(2) End-User I/O Requests and File Objects
微软使用IRP设计用于应用层和驱动层传递数据,并且驱动可以进行继续分层处理(比如文件系统驱动 可能有多个驱动 1级驱动提供读写 2级别提供特定大小的缓存功能的读写)。
我们现在完善上文驱动读写操作
NTSTATUS
DispatchRead(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
DbgPrint("DispatchRead");
UNREFERENCED_PARAMETER(DeviceObject);
//因为分层驱动的设计,所以需要从Irp获取当前层级的参数
PIO_STACK_LOCATION pIrp = IoGetCurrentIrpStackLocation(Irp);
//上册指定缓存区长度
ULONG nLength = pIrp->Parameters.Read.Length;
DbgPrint("DispatchRead buffer:%s bytes:%d", Irp->UserBuffer, nLength);
//拷贝缓冲区
memcpy(Irp->UserBuffer,"helloread",10);
//通知上册成功写入
Irp->iostatus.Status = STATUS_SUCCESS;
//通知上层写入的大小
Irp->IoStatus.Information = 10;
//回调给io处理器完成请求
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
其他读写操作类似就不再举例
#include <Ntddk.h>
//这个函数被注册用于驱动卸载调用
VOID myUnload(
struct _DRIVER_OBJECT* DriverObject
)
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("hello drive unloaded");
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
if (DriverObject->DeviceObject != NULL)
DbgPrint("驱动文件不为空执行删除");
IoDeleteDevice(DeviceObject);
UNICODE_STRING symbolDevName;
RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
IoDeleteSymbolicLink(&symbolDevName);
NTSTATUS
DispatchCreate(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
DbgPrint("DispatchCreate");
return STATUS_SUCCESS;
NTSTATUS
DispatchClose(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
DbgPrint("DispatchClose");
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
NTSTATUS
DispatchRead(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
DbgPrint("DispatchRead");
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION pIrp = IoGetCurrentIrpStackLocation(Irp);
ULONG nLength = pIrp->Parameters.Read.Length;
DbgPrint("DispatchRead buffer:%s bytes:%d", Irp->UserBuffer, nLength);
memcpy(Irp->UserBuffer,"helloread",10);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 10;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
NTSTATUS
DispatchWrite(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
DbgPrint("DispatchWrite");
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION pIrp = IoGetCurrentIrpStackLocation(Irp);
ULONG nLength = pIrp->Parameters.Write.Length;
DbgPrint("DispatchWrite buffer:%s bytes:%d", Irp->UserBuffer, nLength);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 6;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
NTSTATUS
DispatchControl(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
)
DbgPrint("DispatchControl");
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
_In_ struct _DRIVER_OBJECT* DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
//如果你没有用到参数需要告诉系统。
UNREFERENCED_PARAMETER(RegistryPath);
//打印信息
DbgPrint("hello drive loaded");
//触发一个断点
//DbgBreakPoint();
//驱动卸载回调注册
DriverObject->DriverUnload = myUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
UNICODE_STRING ustrDevName;
RtlInitUnicodeString(&ustrDevName, L"\\\\Device\\\\MytestDriver");
PDEVICE_OBJECT pDevObj = NULL;
auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateDevice 成功 \\r\\n");
else
DbgPrint("IoCreateDevice 失败 %d\\r\\n", ret);
return STATUS_FAIL_CHECK;
UNICODE_STRING symbolDevName;
RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
if (NT_SUCCESS(ret))
DbgPrint("IoCreateSymbolicLink 成功 \\r\\n");
else
DbgPrint("IoCreateSymbolicLink 失败%d\\r\\n", ret);
IoDeleteDevice(pDevObj);
return STATUS_FAIL_CHECK;
return STATUS_SUCCESS;
最后写一个应用层代码进行读写
// InvotationDevApp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<Windows.h>
#include<stdlib.h>
int main()
std::cout << "Hello World!\\n";
HANDLE hFile;
hFile = CreateFile("\\\\\\\\\\?\\\\MytestDriver",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
std::cout << "INVALID_HANDLE_VALUE "<< GetLastError()<<"\\n";
return EXIT_FAILURE;
std::cout << "open ok\\n";
DWORD dwBytes = 0;
if (WriteFile(hFile, "hello", 6, &dwBytes, NULL))
std::cout << "write ok " << dwBytes << std::endl;
else
std::cout << "write failure " << dwBytes << std::endl;
DWORD drBytes = 0;
char szBuffer[120];
if (ReadFile(hFile, szBuffer, sizeof szBuffer, &drBytes, NULL))
std::cout << "read ok " << drBytes << " "<< szBuffer << std::endl;
else
std::cout << "read failure " << std::endl;
CloseHandle(hFile);
system("pause");
return EXIT_SUCCESS;
reference
(1) a simple demo for WDM driver
(2) End-User I/O Requests and File Objects
以上是关于windows 驱动与内核调试 学习2的主要内容,如果未能解决你的问题,请参考以下文章