Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

irp->UserBuffer always Empty for IRP_MJ_DEVICE_CONTROL

NtKernelMCNtKernelMC Member Posts: 4

I have two macroes for IO calls

define IOCTL_GET_PROCID CTL_CODE(0x00008000, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)

define IOCTL_INJECT_DLL CTL_CODE(0x00008000, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)

and also have pDriverObject->Flags |= DO_BUFFERED_IO; in Driver entry
but still my user buffer is empty when i call DeviceIoControl from my app.
Full source of driver

include <ntifs.h>

include <ntddk.h>

include <wdf.h>

include <wdm.h>

include <windef.h>

include <ntdef.h>

include <parallel.h>

include <initguid.h>

include <wdmguid.h>

include <stdio.h>

include <stdlib.h>

pragma warning (disable: 4189)

pragma warning (disable: 4100)

pragma warning (disable: 4995)

pragma warning (disable: 4101)

define IOCTL_GET_PROCID CTL_CODE(0x00008000, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)

define IOCTL_INJECT_DLL CTL_CODE(0x00008000, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)

define DRIVER_FUNC_INSTALL 0x01

define DRIVER_FUNC_REMOVE 0x02

define DRIVER_NAME "KernelFucker"

define NT_DEVICE_NAME L"\Device\KernelFucker"

define DOS_DEVICE_NAME L"\DosDevices\KernelFucker"

DRIVER_INITIALIZE DriverEntry;
DRIVER_UNLOAD UnloadRoutine;
NTSTATUS CreateController(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS WriteController(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS CloseController(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS DeviceController(IN PDEVICE_OBJECT fdo, IN PIRP irp);

pragma alloc_text (INIT, DriverEntry)

pragma alloc_text(PAGE, CreateController)

pragma alloc_text(PAGE, WriteController)

pragma alloc_text(PAGE, CloseController)

pragma alloc_text(PAGE, DeviceController)

pragma alloc_text(PAGE, UnloadRoutine)

//typedef NTSTATUS(PLDR_LOAD_DLL)(PWSTR, PULONG, PUNICODE_STRING, PVOID);
void UnloadRoutine(struct _DRIVER_OBJECT *DriverObject)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Unloaded Routine!\n");
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING uniWin32NameString;
PAGED_CODE();
RtlInitUnicodeString(&uniWin32NameString, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&uniWin32NameString);
if (deviceObject != NULL)
{
IoDeleteDevice(deviceObject);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "I\O unhooked.\n");
}
NTSTATUS CreateController(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Created Dispatcher!\r\n");
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS WriteController(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Write Dispatcher!\r\n");
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS CloseController(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Closed Dispatcher!\r\n");
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DeviceController(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
PVOID pBuffer = NULL; static char RetBuffer[] = { "[Ring-0]: Complete!" };
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(irp);
ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
pBuffer = irp->UserBuffer; static char DllPath[256]; static DWORD ProcID;
switch (ControlCode)
{
case IOCTL_GET_PROCID:
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IO Dispatcher called!\r\n");
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Control Code: %d | IOCTL_GET_PROCID\r\n", ControlCode);
ProcID = atoi(pBuffer);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcID: %d\r\n", ProcID);
RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, &RetBuffer, InputLength);
break;
case IOCTL_INJECT_DLL:
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IO Dispatcher called!\r\n");
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Control Code: %d | IOCTL_INJECT_DLL\r\n", ControlCode);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Inc Buffer Size: %d\r\n", InputLength);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Out Buffer Size: %d\r\n", OutputLength);
memcpy(DllPath, pBuffer, sizeof(DllPath));
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "DLL Path: %s\r\n", DllPath);
RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, &RetBuffer, InputLength);
break;
}
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = InputLength;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return irp->IoStatus.Status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "DriverEntry Called \r\n");
//MmGetSystemRoutineAddress()
NTSTATUS ntStatus;
UNICODE_STRING ntUnicodeString;
UNICODE_STRING ntWin32NameString;
PDEVICE_OBJECT deviceObject = NULL;
UNREFERENCED_PARAMETER(RegistryPath);
pDriverObject->MajorFunction[IRP_MJ_CREATE] = CreateController;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = WriteController;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseController;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceController;
pDriverObject->DriverUnload = UnloadRoutine;
RtlInitUnicodeString(&ntUnicodeString, NT_DEVICE_NAME);
ntStatus = IoCreateDevice(pDriverObject, 0, &ntUnicodeString,
FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
if (!NT_SUCCESS(ntStatus))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Couldn't create the device object\n");
return ntStatus;
}
RtlInitUnicodeString(&ntWin32NameString, DOS_DEVICE_NAME);
ntStatus = IoCreateSymbolicLink(&ntWin32NameString, &ntUnicodeString);
if (!NT_SUCCESS(ntStatus))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Couldn't create symbolic link\n");
IoDeleteDevice(deviceObject);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Major hooks placed!\n");
pDriverObject->Flags &= ~DO_DEVICE_INITIALIZING;
pDriverObject->Flags |= DO_BUFFERED_IO;
return STATUS_SUCCESS;
}

Comments

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 6,990

    The pointer to your data buffer isn't in Irp->UserBuffer for buffered I/O... it's in Irp->AssociatedIrp.SystemBuffeer

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • NtKernelMCNtKernelMC Member Posts: 4

    @Peter_Viscarola said:
    The pointer to your data buffer isn't in Irp->UserBuffer for buffered I/O... it's in Irp->AssociatedIrp.SystemBuffeer

    Peter

    But in SystemBuffer pointer to incoming buffer, okay i just need to send in my driver a string. Where my mistake?

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 6,990

    But in SystemBuffer pointer to incoming buffer, okay i just need to send in my driver a string. Where my mistake?

    Sorry... I don't understand your question.

    The data sent to your driver, both the Input and Output buffers, is located at Irp->AssociatedIrp.SystemBuffer. See the section "METHOD_BUFFERED" in MSDN here.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,298

    I lost interest at 'define DRIVER_NAME "KernelFucker"'

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 6,990

    @Mark_Roddy said:
    I lost interest at 'define DRIVER_NAME "KernelFucker"'

    >

    Ah! You READ his code! A step that I bypassed.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • NtKernelMCNtKernelMC Member Posts: 4

    @Mark_Roddy said:
    I lost interest at 'define DRIVER_NAME "KernelFucker"'

    Sorry for that, forgot to rename :cold_sweat: It`s just a name and nothing more)

    @Peter_Viscarola said:

    But in SystemBuffer pointer to incoming buffer, okay i just need to send in my driver a string. Where my mistake?

    Sorry... I don't understand your question.

    The data sent to your driver, both the Input and Output buffers, is located at Irp->AssociatedIrp.SystemBuffer. See the section "METHOD_BUFFERED" in MSDN here.

    Peter

    When i try to read the output buffer i get empty string. As far as i know - output buffer is irp->UserBuffer and incoming buffer is as you sayed - SystemBuffer yeah but i need only outcoming. Cant understand why its always empty like i pointer NULL when calling DeviceIoControl but it`s not, so problem in my driver code. I read many articles about buffered method and not find answer to my question.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 6,990

    As far as i know - output buffer is irp->UserBuffer and incoming buffer is as you sayed - SystemBuffer

    Nope. It’s awlays irp->AssociatedIrp.SystemBuffer. Read the docs I pointed you to. It’s very clear. Irp->UserBuffer is not used in Buffered I/O.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • NtKernelMCNtKernelMC Member Posts: 4

    @Peter_Viscarola said:

    As far as i know - output buffer is irp->UserBuffer and incoming buffer is as you sayed - SystemBuffer

    Nope. It’s awlays irp->AssociatedIrp.SystemBuffer. Read the docs I pointed you to. It’s very clear. Irp->UserBuffer is not used in Buffered I/O.

    Peter

    Thanks! I killed two days for this )

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
Writing WDF Drivers 25 Feb 2019 OSR Seminar Space
Developing Minifilters 8 April 2019 OSR Seminar Space