C驱动编程蓝屏死机

发布于 2024-10-09 21:05:06 字数 4042 浏览 0 评论 0原文

大家好,祝大家除夕/新年快乐,

我目前制作的驱动程序遇到了一些问题。一切工作正常,直到我开始处理 WriteFile() 请求。我的司机试图处理所有事情,但我遇到了蓝屏死机。

我必须查明此语句错误的确切位置:

pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

这是我完整的驱动程序代码(我正在遵循各种教程,所以不要介意可怕的格式,我没有时间整理事情:

#include "ntddk.h"

const WCHAR deviceNameBuffer[] = L"\\Device\\MemoryMirrorDevice";
const WCHAR SymbolicLinkName[] = L"\\DosDevices\\MemoryMirrorLink";
PDEVICE_OBJECT g_DevicePointer= NULL;                      // Global pointer to our device object
int i = 0;
int y;

VOID OnUnload( IN PDRIVER_OBJECT DriverObject ){


UNICODE_STRING SymbolicLinkNameString;

DbgPrint("OnUnload called\n");

    RtlInitUnicodeString(&SymbolicLinkNameString, SymbolicLinkName);
    IoDeleteSymbolicLink(&SymbolicLinkNameString);
    IoDeleteDevice(DriverObject->DeviceObject);


}

int IsStringTerminated(PCHAR pString, unsigned int uiLength){
    int bStringIsTerminated = 0;
    unsigned int uiIndex = 0;

    while(uiIndex < uiLength && bStringIsTerminated == FALSE)
    {
        if(pString[uiIndex] == '\0')
        {
            bStringIsTerminated = 1;
        }
        else
        {
           uiIndex++;
        }
    }

    return bStringIsTerminated;
}



NTSTATUS MyWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp){
    NTSTATUS NtStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIoStackIrp = NULL;
    PCHAR pWriteDataBuffer;

DbgPrint("MyWrite\r\n");

    pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);


    if(pIoStackIrp)
    {


        pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

  return NtStatus;

        if( pWriteDataBuffer != NULL )
        {


           if(IsStringTerminated(pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length))
           {
                DbgPrint(pWriteDataBuffer);
           }
        }
    }

  return NtStatus;
}



void CheckErrors(NTSTATUS ntStatus){
i++;

DbgPrint("%i \n",i);


switch(ntStatus){
case STATUS_INSUFFICIENT_RESOURCES:
DbgPrint("INSUFFICIENT RESOURCES\n");
break;
case STATUS_OBJECT_NAME_EXISTS:
DbgPrint("Name exists\n");
break;
case STATUS_OBJECT_NAME_COLLISION:
DbgPrint("Name collission\n");
break;
case STATUS_SUCCESS:
DbgPrint("Success!\n");
break;
default:
DbgPrint("Error is not filtered!\n");
}
}

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


NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath ){

NTSTATUS ntStatus = STATUS_SUCCESS;
UNICODE_STRING DeviceName;
UNICODE_STRING SymbolicLinkNameString;

DriverObject->DriverUnload = OnUnload;

RtlInitUnicodeString (&DeviceName, deviceNameBuffer );
RtlInitUnicodeString (&SymbolicLinkNameString, SymbolicLinkName);

ntStatus = IoCreateDevice ( DriverObject,0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &g_DevicePointer);
CheckErrors(ntStatus);

if(ntStatus == STATUS_SUCCESS){

ntStatus = IoCreateSymbolicLink( &SymbolicLinkNameString,  &DeviceName);
CheckErrors(ntStatus);
}

for(y = 0; y < IRP_MJ_MAXIMUM_FUNCTION; y++ ){
DriverObject->MajorFunction[y] = OnStubDispatch;
}
DriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;


return STATUS_SUCCESS;
}

代码失败了当我的驱动程序收到 IRp 写入请求时:

#include <iostream>
#include <windows.h>
using namespace std;



int _cdecl main(void){
    HANDLE hFile;
    DWORD dwReturn;
    hFile = CreateFile("\\\\.\\MemoryMirrorLink",
        GENERIC_READ | GENERIC_WRITE, 0, NULL,
        OPEN_EXISTING, 0, NULL);
    if(hFile){
        WriteFile(hFile, "Hello from user mode!",sizeof("Hello from user mode!"), &dwReturn, NULL);
        printf("Succes!");
        CloseHandle(hFile);

    } else {
printf("kthxbye: "); 
cerr<<GetLastError()<<endl;
    }

    cin.ignore();
    return 0;
}

有谁知道我做错了什么? 非常感谢帮助!

Hello and a happy new years eve/new year everybody,

I'm having some problems with the driver I'm currently making. Everything works fine up until I get to handle an WriteFile() request. My driver tries to handle everything but I get a blue screen of death.

I got to pinpoint the exact location of the error to this statement:

pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

Here is my complete driver code (I was following various tutorials so don't mind the horrible format, I haven't had time to tidy things up:

#include "ntddk.h"

const WCHAR deviceNameBuffer[] = L"\\Device\\MemoryMirrorDevice";
const WCHAR SymbolicLinkName[] = L"\\DosDevices\\MemoryMirrorLink";
PDEVICE_OBJECT g_DevicePointer= NULL;                      // Global pointer to our device object
int i = 0;
int y;

VOID OnUnload( IN PDRIVER_OBJECT DriverObject ){


UNICODE_STRING SymbolicLinkNameString;

DbgPrint("OnUnload called\n");

    RtlInitUnicodeString(&SymbolicLinkNameString, SymbolicLinkName);
    IoDeleteSymbolicLink(&SymbolicLinkNameString);
    IoDeleteDevice(DriverObject->DeviceObject);


}

int IsStringTerminated(PCHAR pString, unsigned int uiLength){
    int bStringIsTerminated = 0;
    unsigned int uiIndex = 0;

    while(uiIndex < uiLength && bStringIsTerminated == FALSE)
    {
        if(pString[uiIndex] == '\0')
        {
            bStringIsTerminated = 1;
        }
        else
        {
           uiIndex++;
        }
    }

    return bStringIsTerminated;
}



NTSTATUS MyWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp){
    NTSTATUS NtStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIoStackIrp = NULL;
    PCHAR pWriteDataBuffer;

DbgPrint("MyWrite\r\n");

    pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);


    if(pIoStackIrp)
    {


        pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

  return NtStatus;

        if( pWriteDataBuffer != NULL )
        {


           if(IsStringTerminated(pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length))
           {
                DbgPrint(pWriteDataBuffer);
           }
        }
    }

  return NtStatus;
}



void CheckErrors(NTSTATUS ntStatus){
i++;

DbgPrint("%i \n",i);


switch(ntStatus){
case STATUS_INSUFFICIENT_RESOURCES:
DbgPrint("INSUFFICIENT RESOURCES\n");
break;
case STATUS_OBJECT_NAME_EXISTS:
DbgPrint("Name exists\n");
break;
case STATUS_OBJECT_NAME_COLLISION:
DbgPrint("Name collission\n");
break;
case STATUS_SUCCESS:
DbgPrint("Success!\n");
break;
default:
DbgPrint("Error is not filtered!\n");
}
}

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


NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath ){

NTSTATUS ntStatus = STATUS_SUCCESS;
UNICODE_STRING DeviceName;
UNICODE_STRING SymbolicLinkNameString;

DriverObject->DriverUnload = OnUnload;

RtlInitUnicodeString (&DeviceName, deviceNameBuffer );
RtlInitUnicodeString (&SymbolicLinkNameString, SymbolicLinkName);

ntStatus = IoCreateDevice ( DriverObject,0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &g_DevicePointer);
CheckErrors(ntStatus);

if(ntStatus == STATUS_SUCCESS){

ntStatus = IoCreateSymbolicLink( &SymbolicLinkNameString,  &DeviceName);
CheckErrors(ntStatus);
}

for(y = 0; y < IRP_MJ_MAXIMUM_FUNCTION; y++ ){
DriverObject->MajorFunction[y] = OnStubDispatch;
}
DriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;


return STATUS_SUCCESS;
}

The code fails the moment my driver receives a IRp write request:

#include <iostream>
#include <windows.h>
using namespace std;



int _cdecl main(void){
    HANDLE hFile;
    DWORD dwReturn;
    hFile = CreateFile("\\\\.\\MemoryMirrorLink",
        GENERIC_READ | GENERIC_WRITE, 0, NULL,
        OPEN_EXISTING, 0, NULL);
    if(hFile){
        WriteFile(hFile, "Hello from user mode!",sizeof("Hello from user mode!"), &dwReturn, NULL);
        printf("Succes!");
        CloseHandle(hFile);

    } else {
printf("kthxbye: "); 
cerr<<GetLastError()<<endl;
    }

    cin.ignore();
    return 0;
}

Does anyone know what I'm doing wrong?
Help is very much appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

誰ツ都不明白 2024-10-16 21:05:06

Irp->MdlAddress 可能为 NULL,请使用 Irp->UserBuffer 代替。

熟悉内核调试器和诊断蓝屏。你会需要它。

Irp->MdlAddress is probably NULL, use Irp->UserBuffer instead.

Get familiar with the kernel debugger and diagnosing blue screens. You'll need it.

筱果果 2024-10-16 21:05:06

汉斯的答案是正确的,只需发布​​更多内容,可能会帮助您使用某些内核调试器调试进一步的问题。

这是(一部分)!analyze 输出

BUGCHECK_STR:  ACCESS_VIOLATION

DEFAULT_BUCKET_ID:  NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER:  from 804e3d77 to f7bd6549

STACK_TEXT:  
f3931c60 804e3d77 85e1eca8 85d8f7a0 806ed070 test_drv!MyWrite+0x39 [c:\fiddle\test_drv\drv.c @ 58]
WARNING: Stack unwind information not available. Following frames may be wrong.
f3931c84 8057a510 85e1eca8 85d8f7a0 85c76788 nt!IofCallDriver+0x32
f3931d38 804df06b 000007e8 00000000 00000000 nt!NtWriteFile+0x3eb
f3931ddc 804fa477 f72d9b85 85c79340 00000000 nt!ZwYieldExecution+0xb96
f3931e20 7c90e027 7c80b1f9 ffffffff 00000017 nt!KeInitializeTimer+0x10c
00000000 00000000 00000000 00000000 00000000 ntdll+0xe027


STACK_COMMAND:  kb

FAULTING_SOURCE_CODE:  
    54:     if(pIoStackIrp)
    55:     {
    56: 
    57: 
>   58:     pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    59: 
    60:     return NtStatus;
    61: 
    62:     if( pWriteDataBuffer != NULL )
    63:     {

,这里是 Irp 的内容,

kd> dt Irp
Local var @ 0xf3931c6c Type _IRP*
0x85d8f7a0 
   +0x000 Type             : 0n6
   +0x002 Size             : 0x94
   +0x004 MdlAddress       : (null) 
   +0x008 Flags            : 0xa00
   +0x00c AssociatedIrp    : <unnamed-tag>
   +0x010 ThreadListEntry  : _LIST_ENTRY [ 0x85e27560 - 0x85e27560 ]
   +0x018 IoStatus         : _IO_STATUS_BLOCK
   +0x020 RequestorMode    : 1 ''
   +0x021 PendingReturned  : 0 ''
   +0x022 StackCount       : 1 ''
   +0x023 CurrentLocation  : 1 ''
   +0x024 Cancel           : 0 ''
   +0x025 CancelIrql       : 0 ''
   +0x026 ApcEnvironment   : 0 ''
   +0x027 AllocationFlags  : 0xc ''
   +0x028 UserIosb         : 0x0012ff34 _IO_STATUS_BLOCK
   +0x02c UserEvent        : (null) 
   +0x030 Overlay          : <unnamed-tag>
   +0x038 CancelRoutine    : (null) 
   +0x03c UserBuffer       : 0x0041c1d8 Void
   +0x040 Tail             : <unnamed-tag>

您可以检查 MdlAddress 是否为 NULL,并且您要传递给的函数“MmGetSystemAddressForMdlSafe”需要第一个参数“指向缓冲区的指针,该缓冲区对应的基虚拟地址”地址将被映射。

希望这会有所帮助:)

Hans's answer is correct, just posting a few more things that might help you in debugging further issues with some kernel debugger.

Here is (a part of) !analyze output

BUGCHECK_STR:  ACCESS_VIOLATION

DEFAULT_BUCKET_ID:  NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER:  from 804e3d77 to f7bd6549

STACK_TEXT:  
f3931c60 804e3d77 85e1eca8 85d8f7a0 806ed070 test_drv!MyWrite+0x39 [c:\fiddle\test_drv\drv.c @ 58]
WARNING: Stack unwind information not available. Following frames may be wrong.
f3931c84 8057a510 85e1eca8 85d8f7a0 85c76788 nt!IofCallDriver+0x32
f3931d38 804df06b 000007e8 00000000 00000000 nt!NtWriteFile+0x3eb
f3931ddc 804fa477 f72d9b85 85c79340 00000000 nt!ZwYieldExecution+0xb96
f3931e20 7c90e027 7c80b1f9 ffffffff 00000017 nt!KeInitializeTimer+0x10c
00000000 00000000 00000000 00000000 00000000 ntdll+0xe027


STACK_COMMAND:  kb

FAULTING_SOURCE_CODE:  
    54:     if(pIoStackIrp)
    55:     {
    56: 
    57: 
>   58:     pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    59: 
    60:     return NtStatus;
    61: 
    62:     if( pWriteDataBuffer != NULL )
    63:     {

and here is the content of Irp

kd> dt Irp
Local var @ 0xf3931c6c Type _IRP*
0x85d8f7a0 
   +0x000 Type             : 0n6
   +0x002 Size             : 0x94
   +0x004 MdlAddress       : (null) 
   +0x008 Flags            : 0xa00
   +0x00c AssociatedIrp    : <unnamed-tag>
   +0x010 ThreadListEntry  : _LIST_ENTRY [ 0x85e27560 - 0x85e27560 ]
   +0x018 IoStatus         : _IO_STATUS_BLOCK
   +0x020 RequestorMode    : 1 ''
   +0x021 PendingReturned  : 0 ''
   +0x022 StackCount       : 1 ''
   +0x023 CurrentLocation  : 1 ''
   +0x024 Cancel           : 0 ''
   +0x025 CancelIrql       : 0 ''
   +0x026 ApcEnvironment   : 0 ''
   +0x027 AllocationFlags  : 0xc ''
   +0x028 UserIosb         : 0x0012ff34 _IO_STATUS_BLOCK
   +0x02c UserEvent        : (null) 
   +0x030 Overlay          : <unnamed-tag>
   +0x038 CancelRoutine    : (null) 
   +0x03c UserBuffer       : 0x0041c1d8 Void
   +0x040 Tail             : <unnamed-tag>

You can check that MdlAddress is NULL and the function 'MmGetSystemAddressForMdlSafe' to which you are passing this expects the first argument a 'Pointer to a buffer whose corresponding base virtual address is to be mapped.'

Hope this will help :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文