ZBLOG

windows内核开发,写一个用户态调用writeFile时,内核态不从UserBuffer中取数据,而是从MDL中取数据的demo

在 Windows 内核开发中,如果你想要在处理 WriteFile 调用时,从内存描述符列表(MDL,Memory Descriptor List)而不是用户缓冲区读取数据,你需要了解 Windows 内核的 I/O 体系结构。以下是一个简化的示例,演示如何通过内核模式驱动程序实现这个功能。

环境准备

  1. Windows Driver Kit (WDK):确保你已经安装了 WDK。
  2. Visual Studio:使用 Visual Studio 创建和编译驱动程序。

示例代码

下面的代码是一个简单的 Windows 驱动程序,它拦截 WriteFile 系统调用,并从 MDL 中读取数据,而不是从用户提供的缓冲区。

1. 驱动程序代码

  1. #include <ntddk.h>
  2. NTSTATUS MyDriverDispatchWrite(
  3. PDEVICE_OBJECT DeviceObject,
  4. PIRP Irp)
  5. {
  6. PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
  7. ULONG bufferLength = ioStack->Parameters.Write.Length;
  8. // 获取MDL指针
  9. PMDL mdl = Irp->MdlAddress;
  10. // 在这里,你可以根据需要进行一些检查
  11. if (!mdl) {
  12. return STATUS_INVALID_PARAMETER;
  13. }
  14. // 从MDL中获取数据
  15. PVOID mdlBuffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
  16. if (!mdlBuffer) {
  17. return STATUS_INSUFFICIENT_RESOURCES;
  18. }
  19. // 假设我们从 MDL 中获得的数据长度与 Write 的长度相同
  20. ULONG bytesToWrite = min(bufferLength, MmGetMdlByteCount(mdl));
  21. // 将 MDL 数据打印到调试输出
  22. DbgPrint("Writing %lu bytes from MDL: %s\n", bytesToWrite, (char*)mdlBuffer);
  23. // 设置 IRP 完成状态
  24. Irp->IoStatus.Status = STATUS_SUCCESS;
  25. Irp->IoStatus.Information = bytesToWrite; // 返回写入字节数
  26. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  27. return STATUS_SUCCESS;
  28. }
  29. NTSTATUS MyDriverCreateClose(
  30. PDEVICE_OBJECT DeviceObject,
  31. PIRP Irp)
  32. {
  33. Irp->IoStatus.Status = STATUS_SUCCESS;
  34. Irp->IoStatus.Information = 0;
  35. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  36. return STATUS_SUCCESS;
  37. }
  38. void DriverUnload(PDRIVER_OBJECT DriverObject)
  39. {
  40. UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDevice");
  41. IoDeleteSymbolicLink(&symLinkName);
  42. IoDeleteDevice(DriverObject->DeviceObject);
  43. }
  44. extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  45. {
  46. UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDevice");
  47. UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDevice");
  48. PDEVICE_OBJECT deviceObject;
  49. NTSTATUS status = IoCreateDevice(DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN,
  50. 0, FALSE, &deviceObject);
  51. if (NT_SUCCESS(status)) {
  52. status = IoCreateSymbolicLink(&symLinkName, &deviceName);
  53. if (NT_SUCCESS(status)) {
  54. DriverObject->MajorFunction[IRP_MJ_CREATE] = MyDriverCreateClose;
  55. DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDriverCreateClose;
  56. DriverObject->MajorFunction[IRP_MJ_WRITE] = MyDriverDispatchWrite;
  57. DriverObject->DriverUnload = DriverUnload;
  58. } else {
  59. IoDeleteDevice(deviceObject);
  60. }
  61. }
  62. return status;
  63. }

2. 编译和加载驱动程序

  • 使用 Visual Studio 创建一个新的驱动项目,将上述代码添加到项目中。
  • 配置项目以生成 WDF 驱动,并确保正确设置编译目标为“Release”或“Debug”模式。
  • 构建驱动并使用工具(如 sc.exedevcon.exe)加载和卸载驱动。

注意事项

  1. 调试信息:可以使用 DebugView 等工具查看从 DbgPrint 输出的信息。
  2. 权限:确保以管理员权限运行相关操作,以便能够加载/卸载驱动程序。
  3. 错误处理:在实际应用中,应当考虑更多错误处理逻辑,例如检查函数返回值等。
  4. 稳定性与安全性:直接操作内存涉及到潜在风险,尤其是在实际产品环境中,应特别小心。

这只是一个非常基础的示例,在实际应用中可能还需要考虑线程安全、同步以及资源管理等问题。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=19086

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?