使用RtlCopyMemory在驱动程序中复制数据

时间:2015-11-22 19:22:10

标签: c# c++ driver windbg

我有两个驱动程序和C#应用程序。有了这个应用程序,我可以从设备中写入和读取值。我正在使用第一个驱动程序将数据从用户传递到第二个驱动程序,我从第一个驱动程序调用。然后我用RtlCopyMemory复制数据。问题是这个函数导致访问冲突因为null参数(我将在下面的代码中显示这究竟发生了什么 - 我发现通过使用WinDbg进行调试)。我相信其中一个驱动程序中的错误位于DispatchWrite

第一个驱动程序

NTSTATUS DispatchWrite (
        IN PDEVICE_OBJECT   pDevObj,
        IN PIRP             pIrp            ) 
{

    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ FIRST - DispatchWrite ]\n");
    #endif

    NTSTATUS status = STATUS_SUCCESS;
    PVOID userBuffer;
    ULONG xferSize;

    PIO_STACK_LOCATION pIrpNext;
    PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation( pIrp );

    IoCopyCurrentIrpStackLocationToNext(pIrp);
    //IoSkipCurrentIrpStackLocation(pIrp);
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;

    status=IoCallDriver(pDevExt->pTargetDeviceObject, pIrp);


    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ FIRST - DispatchWrite - End ]\n");
    #endif

    return status;
}

第二个驱动程序

NTSTATUS DispatchWrite (
        IN PDEVICE_OBJECT   pDevObj,
        IN PIRP             pIrp            ) 
{

    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ SECOND - DispatchWrite ]\n");
    #endif

    NTSTATUS status = STATUS_SUCCESS;
    PVOID userBuffer;
    ULONG xferSize;

    PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;

    if (pDevExt->deviceBuffer != NULL) 
    {
        ExFreePool(pDevExt->deviceBuffer);
        pDevExt->deviceBuffer = NULL;
        pDevExt->deviceBufferSize = 0;
    }

    xferSize = pIrpStack->Parameters.Write.Length;
    userBuffer = pIrp->AssociatedIrp.SystemBuffer; //this is NULL
    pDevExt->deviceBuffer = ExAllocatePool( PagedPool, xferSize );

    if (pDevExt->deviceBuffer == NULL) 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        xferSize = 0;
    } 
    else 
    {
        pDevExt->deviceBufferSize = xferSize;
        RtlCopyMemory( pDevExt->deviceBuffer, userBuffer, xferSize ); //userBuffer is null - access violation
    }

    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = xferSize;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );

    return status;
}

C#app

private void button1_Click(object sender, EventArgs e)
        {
            Ster ster = new Ster();
            String devPath = "\\\\.\\";
            devPath += textBox1.Text;
            String userMessage = textBox2.Text;
            ster.driverOpen(devPath);
            ster.driverWrite(userMessage);

        }

Ster class:

public Boolean driverOpen(string deviceName)
        {
            this.DriverHandle = CreateFile(deviceName, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            if (this.DriverHandle.Equals(IntPtr.Zero))
                return false;
            else
                return true;
        }

unsafe public Boolean driverWrite(string UserMessage)
        {
            uint bW;
            StringBuilder Message = new StringBuilder(UserMessage, 26);

            WriteFile(this.DriverHandle, Message, 26, out bW, 0);
            CloseHandle(this.DriverHandle);
            return true;
        }

1 个答案:

答案 0 :(得分:1)

正如IRP所述:

  

AssociatedIrp.SystemBuffer [...]

     

如果驱动程序使用直接I / O,则[...] NULL

IRP_MJ_WRITE下:

  

输入参数

     

[...]

     

Irp的缓冲区> AssociatedIrp.SystemBuffer,如果驱动程序使用缓冲的I / O

     

MDL在Irp-> MdlAddress描述的缓冲区,如果[...]驱动程序使用直接I / O

(强调我的。)

IoW,您描述的行为完全符合预期。当驱动程序配置为直接I / O时,SystemBuffer参数假设设置为NULL

您必须重新配置驱动程序以使用缓冲I / O,或使用MDL访问用户缓冲区。

NB:在这种情况下,我不确定是第一个还是第二个驱动程序的配置控制传递哪个参数。