Драйвер режима ядра BSOD PAGE_FAULT_IN_NONPAGED_AREA с использованием глобального UNICODE_STRING в обратном вызове - PullRequest
1 голос
/ 27 марта 2020

У меня возникает проблема с BSOD (PAGE_FAULT_IN_NONPAGED_AREA), которая только начинается, когда я добавляю свою UNICODE_STRING

Система cra sh происходит после того, как UNICODE_STRING установлена ​​и работает примерно через 10 минут или так система вылетает из ниоткуда. Может быть, потому что я перезаписываю UNICODE_STRING много раз?

WinDBG говорит, что мне нужно использовать probe(), чтобы эта ошибка не возникала.

мне нужно использовать что-то подобное? в обратном вызове перед оператором if? ProbeForRead(ProcessName.Buffer, ProcessName.MaximumLength, sizeof(UCHAR));

Вот мой MEMORY.DMP

Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\Windows\MEMORY.DMP]
Kernel Summary Dump File: Only kernel address space is available

Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path.           *
* Use .symfix to have the debugger choose a symbol path.                   *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is: 
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntkrnlmp.exe - 
Windows 7 Kernel Version 7601 (Service Pack 1) MP (12 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 7601.24545.amd64fre.win7sp1_ldr_escrow.200102-1707
Machine Name:
Kernel base = 0xfffff800`0340a000 PsLoadedModuleList = 0xfffff800`03643c90
Debug session time: Fri Mar 27 07:18:32.627 2020 (UTC - 4:00)
System Uptime: 0 days 1:14:27.811
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntkrnlmp.exe - 
Loading Kernel Symbols
...............................................................
................................................................
................................................
Loading User Symbols
PEB is paged out (Peb.Ldr = 00000000`fffdf018).  Type ".hh dbgerr001" for details
Loading unloaded module list
...........................
ERROR: FindPlugIns 8007007b
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck 50, {fffff8a037f2d000, 0, fffff8000348e46a, 0}

***** Kernel symbols are WRONG. Please fix symbols to do analysis.

Probably caused by : Driver.sys ( Driver!ImageLoadCallback+38 )

Followup: MachineOwner
---------

10: kd> !analyze -v
ERROR: FindPlugIns 8007007b
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except,
it must be protected by a Probe.  Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: fffff8a037f2d000, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff8000348e46a, If non-zero, the instruction address which referenced the bad memory
    address.
Arg4: 0000000000000000, (reserved)

Debugging Details:
------------------

***** Kernel symbols are WRONG. Please fix symbols to do analysis.

ADDITIONAL_DEBUG_TEXT:  
Use '!findthebuild' command to search for the target build information.
If the build information is available, run '!findthebuild -s ; .reload' to set symbol path and load symbols.

MODULE_NAME: Driver

FAULTING_MODULE: fffff8000340a000 nt

DEBUG_FLR_IMAGE_TIMESTAMP:  5e7ddfd8

READ_ADDRESS: unable to get nt!MmSpecialPoolStart
unable to get nt!MmSpecialPoolEnd
unable to get nt!MmPoolCodeStart
unable to get nt!MmPoolCodeEnd
 fffff8a037f2d000 

FAULTING_IP: 
nt!wcsstr+56
fffff800`0348e46a 66418b00        mov     ax,word ptr [r8]

MM_INTERNAL_CODE:  0

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x50

CURRENT_IRQL:  0

LAST_CONTROL_TRANSFER:  from fffff800035779b2 to fffff8000349dea0

STACK_TEXT:  
fffff880`0a6abf38 fffff800`035779b2 : 00000000`00000050 fffff8a0`37f2d000 00000000`00000000 fffff880`0a6ac090 : nt!KeBugCheckEx
fffff880`0a6abf40 fffff800`034a9fdc : 00000000`00000000 fffff8a0`37f2d000 fffff880`0a6ac000 fffffa80`232cfe28 : nt!PoCallDriver+0x4f52
fffff880`0a6ac090 fffff800`0348e46a : fffff880`0aeaf498 00000000`00000001 00000000`00001810 00000000`0000003d : nt!longjmp+0x3c7c
fffff880`0a6ac228 fffff880`0aeaf498 : 00000000`00000001 00000000`00001810 00000000`0000003d fffff8a0`0e903c00 : nt!wcsstr+0x56
fffff880`0a6ac230 fffff800`0370f3e4 : 00000000`00000001 fffff800`036250d8 fffff800`036250d8 00000000`00000000 : Driver!ImageLoadCallback+0x38 [c:\users\igor\desktop\driver memory editor\driver\driver.c @ 499]
fffff880`0a6ac260 fffff800`03839c92 : fffffa80`232cfdd0 fffffa80`1a26b278 fffffa80`20cc59c0 00000000`00000000 : nt!ObDereferenceSecurityDescriptor+0x204
fffff880`0a6ac2c0 fffff800`036fe317 : fffffa80`20cc5980 fffffa80`1a26b060 fffff880`0a6ac570 fffff880`0a6ac568 : nt!IoCreateController+0x2af2
fffff880`0a6ac410 fffff800`036f5aed : ffff845f`00000018 fffffa80`1a26b060 fffff880`0a6ac570 00000000`00000020 : nt!NtOpenThreadTokenEx+0x14b7
fffff880`0a6ac500 fffff800`034abf53 : 00000000`00002760 fffffa80`1efbfb50 00000000`0021ace8 00000000`00000001 : nt!NtMapViewOfSection+0x2bd
fffff880`0a6ac5d0 00000000`779a9a2a : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!longjmp+0x5bf3
00000000`0021acc8 fffff800`034a0cc0 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x779a9a2a
fffff880`0a6ac820 00000000`00000000 : 00000000`01190b90 fffff880`0a6acd18 fffff900`c085eee0 00000000`0043e0a0 : nt!KiCpuId+0xa10


STACK_COMMAND:  kb

FOLLOWUP_IP: 
Driver!ImageLoadCallback+38 [c:\users\igor\desktop\driver memory editor\driver\driver.c @ 499]
fffff880`0aeaf498 4885c0          test    rax,rax

FAULTING_SOURCE_CODE:  
   495:     //DbgPrintEx(0, 0, "Loaded Name: %ls \n", FullImageName->Buffer);
   496:     //DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);
   497: 
   498:     // Compare our string to input
>  499:     if (ProcessName.Length != 0 && wcsstr(FullImageName->Buffer, ProcessName.Buffer)) {
   500:         // if it matches
   501:         DbgPrintEx(0, 0, "Loaded Name: %ls \n", FullImageName->Buffer);
   502:         DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);
   503: 
   504:         GameBaseAddress = ImageInfo->ImageBase;


SYMBOL_STACK_INDEX:  4

SYMBOL_NAME:  Driver!ImageLoadCallback+38

FOLLOWUP_NAME:  MachineOwner

IMAGE_NAME:  Driver.sys

BUCKET_ID:  WRONG_SYMBOLS

Followup: MachineOwner
---------


Исходный код:

// Request to retrieve the process id of game process, from kernel space
#define IO_SET_PROCESS_NAME_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0703 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)

ULONG GameProcessId, GameBaseAddress;
UNICODE_STRING  ProcessName;

// set a callback for every PE image loaded to user memory
// then find the base address & game.exe process id using the callback
PLOAD_IMAGE_NOTIFY_ROUTINE ImageLoadCallback(PUNICODE_STRING FullImageName,
    HANDLE ProcessId, PIMAGE_INFO ImageInfo)
{
    //DbgPrintEx(0, 0, "Loaded Name: %ls \n", FullImageName->Buffer);
    //DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);

    // Compare our string to input
    if (ProcessName.Length != 0 && wcsstr(FullImageName->Buffer, ProcessName.Buffer)) {
        // if it matches
        DbgPrintEx(0, 0, "Loaded Name: %ls \n", FullImageName->Buffer);
        DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);

        GameBaseAddress = ImageInfo->ImageBase;
        GameProcessId = ProcessId;
    }
}

//Here is my IOCTL Call Handler
// IOCTL Call Handler function
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS Status;
    ULONG BytesIO = 0;

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

    // Code received from user space
    ULONG ControlCode = stack->Parameters.DeviceIoControl.IoControlCode;

    if (ControlCode == IO_SET_PROCESS_NAME_REQUEST)
    {
        ULONG inBufLength = stack->Parameters.DeviceIoControl.InputBufferLength; // Input buffer length
        ULONG outBufLength = stack->Parameters.DeviceIoControl.OutputBufferLength; // Output buffer length

        if (inBufLength == 0) {
            DbgPrint("Invalid Process name size detected\n");
            Status = STATUS_INVALID_PARAMETER;
            BytesIO = 0;
            goto finish;
        }

        PWSTR processBuffer;

        // Allocate the buffer that will contain the string
        processBuffer = ExAllocatePoolWithTag(NonPagedPool, stack->Parameters.DeviceIoControl.InputBufferLength+2, '5PWA');
        if(processBuffer == NULL){
            DbgPrint("Unable to allocate the Process Buffer: not enough memory.\n");
            Status = STATUS_INSUFFICIENT_RESOURCES;
            BytesIO = 0;
            goto finish;
        }

        // Copy the buffer
        RtlCopyBytes((PVOID)processBuffer, Irp->AssociatedIrp.SystemBuffer, stack->Parameters.DeviceIoControl.InputBufferLength);
        //RtlMoveMemory((PVOID)processBuffer, Irp->AssociatedIrp.SystemBuffer, stack->Parameters.DeviceIoControl.InputBufferLength);

        // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
        ((PSHORT)processBuffer)[(stack->Parameters.DeviceIoControl.InputBufferLength+2)/2-1]=0;

        // Create the Unicode string
        BOOLEAN success = RtlCreateUnicodeString(&ProcessName, processBuffer);

        ExFreePool(processBuffer);

        if (success) {
            DbgPrint("Set New Process to %ws, len=%d\n", ProcessName.Buffer, stack->Parameters.DeviceIoControl.InputBufferLength);
            Status = STATUS_SUCCESS;
            BytesIO = 0;
        } else {
            DbgPrint("Failed to allocate Unicode String for Process\n");
            Status = STATUS_INSUFFICIENT_RESOURCES;
            BytesIO = 0;
        }
    }
    else
    {
         // if the code is unknown
        Status = STATUS_INVALID_PARAMETER;
        BytesIO = 0;
    }
finish:
    // Complete the request
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = BytesIO;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Status;
}

// Driver Entrypoint
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
    PUNICODE_STRING pRegistryPath)
{
    DbgPrintEx(0, 0, "Driver Loaded\n");

    PsSetLoadImageNotifyRoutine(ImageLoadCallback);

    RtlInitUnicodeString(&dev, deviceNameBuffer);
    RtlInitUnicodeString(&dos, deviceSymLinkBuffer);

    IoCreateDevice(pDriverObject, 0, &dev, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
    IoCreateSymbolicLink(&dos, &dev);

    pDriverObject->MajorFunction[IRP_MJ_CREATE] = CreateCall;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseCall;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoControl;
    pDriverObject->DriverUnload = UnloadDriver;

    pDeviceObject->Flags |= DO_DIRECT_IO;
    pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    return STATUS_SUCCESS;
}

NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriverObject)
{
    DbgPrintEx(0, 0, "Unload routine called.\n");

    PsRemoveLoadImageNotifyRoutine(ImageLoadCallback);
    IoDeleteSymbolicLink(&dos);
    IoDeleteDevice(pDriverObject->DeviceObject);
}

NTSTATUS CreateCall(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
    irp->IoStatus.Status = STATUS_SUCCESS;
    irp->IoStatus.Information = 0;

    IoCompleteRequest(irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS CloseCall(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
    irp->IoStatus.Status = STATUS_SUCCESS;
    irp->IoStatus.Information = 0;

    IoCompleteRequest(irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
...