My Windows driver use a PLOAD_IMAGE_NOTIFY_ROUTINE callback to get the image path for a specified process. I want to send this path (parameter FullImagePathName, which is a PUNICODE_STRING) to a usermode client, and display it. I think the first step would be to assign the copy the FullImagePathName to an other UNICODE_STRING which is available from my IOCTL function, then find a way to send it to the client. I already tried to play with some string copy functions with WCHAR and FullImagePath->Buffer, but no success. How can I proceed ?
void sSetNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) {
UNREFERENCED_PARAMETER(ImageInfo);
PEPROCESS process = NULL;
PUNICODE_STRING processName;
UNICODE_STRING lsass_prefix;
RtlInitUnicodeString(&lsass_prefix, L"\\Device\\HarddiskVolume4\\Windows\\System32\\lsass.exe");
PsLookupProcessByProcessId(ProcessId, &process);
SeLocateProcessImageName(process,&processName);
if (compare_punicode(processName, &lsass_prefix) == 0) {
DbgPrint("Ok\n");
DbgPrint("lsass launched %wZ\n", FullImageName);
}
//DbgPrint("%wZ (%d) loaded %wZ", processName, ProcessId, FullImageName);
}
Here is my IOCTL function code :
NTSTATUS
DeviceControl(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR length = 0;
switch (stack->Parameters.DeviceIoControl.IoControlCode)
{
case FIRST_DRIVER_IOCTL_TEST:
if (lsass_string) {
DbgPrint("[+] FIRST_DRIVER_IOCTL_TEST called\n");
if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CHAR*))
{
status = STATUS_BUFFER_TOO_SMALL;
DbgPrint("[!] STATUS_BUFFER_TOO_SMALL\n");
break;
}
else {
if (lsass_string == NULL)
{
status = STATUS_INVALID_PARAMETER;
DbgPrint("[!] STATUS_INVALID_PARAMETER\n");
break;
}
else {
DbgPrint("sending to usermode\n");
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, lsass_string, strlen(Irp->AssociatedIrp.SystemBuffer));
}
}
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
DbgPrint("[!] STATUS_INVALID_DEVICE_REQUEST\n");
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
Please note that "lsass_string" and "CHAR*" are for information only, and are not working code.