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 //这个函数被注册用于驱动卸载调用
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 //这个函数被注册用于驱动卸载调用
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 //这个函数被注册用于驱动卸载调用
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 
#include
#include
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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部