irp->UserBuffer always Empty for IRP_MJ_DEVICE_CONTROL

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;
}

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

Peter

@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?

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

I lost interest at ‘define DRIVER_NAME “KernelFucker”’

@Mark_Roddy said:
I lost interest at ‘define DRIVER_NAME “KernelFucker”’

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

Peter

@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.

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 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 )