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. 驱动程序代码

#include <ntddk.h>

NTSTATUS MyDriverDispatchWrite(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp)
{
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG bufferLength = ioStack->Parameters.Write.Length;
    
    // 获取MDL指针
    PMDL mdl = Irp->MdlAddress;

    // 在这里,你可以根据需要进行一些检查
    if (!mdl) {
        return STATUS_INVALID_PARAMETER;
    }

    // 从MDL中获取数据
    PVOID mdlBuffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
    
    if (!mdlBuffer) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    // 假设我们从 MDL 中获得的数据长度与 Write 的长度相同
    ULONG bytesToWrite = min(bufferLength, MmGetMdlByteCount(mdl));

    // 将 MDL 数据打印到调试输出
    DbgPrint("Writing %lu bytes from MDL: %s\n", bytesToWrite, (char*)mdlBuffer);

    // 设置 IRP 完成状态
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = bytesToWrite;  // 返回写入字节数
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return STATUS_SUCCESS;
}

NTSTATUS MyDriverCreateClose(
   PDEVICE_OBJECT DeviceObject,
   PIRP Irp)
{
   Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);
   return STATUS_SUCCESS;
}

void DriverUnload(PDRIVER_OBJECT DriverObject)
{
   UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDevice");
   IoDeleteSymbolicLink(&symLinkName);
   IoDeleteDevice(DriverObject->DeviceObject);
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
   UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDevice");
   UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDevice");
   
   PDEVICE_OBJECT deviceObject;

   NTSTATUS status = IoCreateDevice(DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN,
                                     0, FALSE, &deviceObject);

   if (NT_SUCCESS(status)) {
       status = IoCreateSymbolicLink(&symLinkName, &deviceName);
       if (NT_SUCCESS(status)) {
           DriverObject->MajorFunction[IRP_MJ_CREATE] = MyDriverCreateClose;
           DriverObject->MajorFunction[IRP_MJ_CLOSE]  = MyDriverCreateClose;
           DriverObject->MajorFunction[IRP_MJ_WRITE]  = MyDriverDispatchWrite;

           DriverObject->DriverUnload = DriverUnload;
       } else {
           IoDeleteDevice(deviceObject);
       }
   }

   return status;
}

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

注册

已经有帐号?