如何在过滤器驱动程序中获取当前进程映像文件全名?

How get current process image file full name in filter driver?

在过滤器驱动程序中,我可以调用 IoGetCurrentProcess 来获取 PEPROCESS 结构,然后调用 PsGetProcessImageFileName 来获取文件名。

我的问题是如何获得过程映像文件的完整名称?

您可以使用 ZwQueryInformationProcess 和 27 的信息 class。下面的代码使用此例程从进程的句柄中获取完整的图像文件名。

NTSTATUS GetProcessNameByHandle(_In_ HANDLE ProcessHandle, _Out_ PUNICODE_STRING *Name)
{
    ULONG retLength = 0;
    ULONG pniSize = 512;
    PUNICODE_STRING pni = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    do {
        pni = (PUNICODE_STRING)ExAllocatePoolWithTag(PagedPool, pniSize, POOL_TAG);
        if (pni != NULL) {
            status = ZwQueryInformationProcess(ProcessHandle, 27, pni, pniSize, &retLength);
            if (!NT_SUCCESS(status)) {
              ExFreePoolWithTag(pni, POOL_TAG); 
              pniSize *= 2;
            }
        } else status = STATUS_INSUFFICIENT_RESOURCES;
    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    if (NT_SUCCESS(status))
        *Name = pni;

    return status;
}

您可以通过以下方式获取进程句柄:

  • ObOpenObjectByPointer,您需要进程的 EPROCESS 地址(PsLookupProcessByProcessId 可能有帮助)。

  • ZwOpenProcess – 你需要知道目标进程的 PID。

然而,在每次调用 minifilter 的 pre/post 回调时使用此代码可能会非常耗时。我通过在使用 PID 作为键的散列 table 中缓存进程名称来解决这个问题。通知例程 (PsSetXXXNotifyRoutine(Ex)) 在构建和管理这样的 table 时可能非常有用。

here 我找到了像@Martin Drab 代码这样的完整代码

编辑:新固定代码

NTSTATUS
GetProcessImageName(
    PEPROCESS eProcess,
    PUNICODE_STRING* ProcessImageName
    )
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG returnedLength;
    HANDLE hProcess = NULL;

    PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process

    if (eProcess == NULL)
    {
        return STATUS_INVALID_PARAMETER_1;
    }

    status = ObOpenObjectByPointer(eProcess,
        0, NULL, 0, 0, KernelMode, &hProcess);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status);
        return status;
    }

    if (ZwQueryInformationProcess == NULL)
    {
        UNICODE_STRING routineName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");

        ZwQueryInformationProcess =
            (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName);

        if (ZwQueryInformationProcess == NULL)
        {
            DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
            status = STATUS_UNSUCCESSFUL;
            goto cleanUp;
        }
    }

    /* Query the actual size of the process path */
    status = ZwQueryInformationProcess(hProcess,
        ProcessImageFileName,
        NULL, // buffer
        0,    // buffer size
        &returnedLength);

    if (STATUS_INFO_LENGTH_MISMATCH != status) {
        DbgPrint("ZwQueryInformationProcess status = %x\n", status);
        goto cleanUp;
    }

    *ProcessImageName = kmalloc(returnedLength);

    if (ProcessImageName == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto cleanUp;
    }

    /* Retrieve the process path from the handle to the process */
    status = ZwQueryInformationProcess(hProcess,
        ProcessImageFileName,
        *ProcessImageName,
        returnedLength,
        &returnedLength);

    if (!NT_SUCCESS(status)) kfree(*ProcessImageName);

cleanUp:

    ZwClose(hProcess);

    return status;
}

FLT_POSTOP_CALLBACK_STATUS
PostCreate(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_opt_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
    )
{
    PUNICODE_STRING pni = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    status = GetProcessImageName(IoThreadToProcess(Data->Thread), &pni);
    if (NT_SUCCESS(status))
    {
        DbgPrint("ProcessName = %ws\n", pni->Buffer);
        kfree(pni);
    }
    else
    {
        DbgPrint("GetProcessImageName status = %x\n", status);
    }

    // ...
}