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

时间:2022-08-22 16:02:45

In filter driver I can call IoGetCurrentProcess to get an PEPROCESS structure, and than call PsGetProcessImageFileName to get file name.

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

My questions is how I can get full name of the process image file?

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

2 个解决方案

#1


1  

You can use ZwQueryInformationProcess with the information class of 27. THe following code uses this routine to obtain the full image file name from process' handle.

您可以将ZwQueryInformationProcess与信息类27一起使用。以下代码使用此例程从进程'句柄获取完整的映像文件名。

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

You can obtain the process handle by the following ways:

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

  • ObOpenObjectByPointer, you need process' EPROCESS address (PsLookupProcessByProcessId may help).

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

  • ZwOpenProcess – youn need to know PID of the target process.

    ZwOpenProcess - 您需要知道目标进程的PID。

However, using this code in every invocation of your minifilter's pre/post callback can be quite time-consuming. I solve this problem by caching process names in a hash table that uses PID as a key. Notify routines (PsSetXXXNotifyRoutine(Ex)) may prove very useful when building and managing such a table.

但是,在每次调用minifilter的前/后回调时使用此代码可能非常耗时。我通过在使用PID作为键的哈希表中缓存进程名来解决此问题。在构建和管理这样的表时,通知例程(PsSetXXXNotifyRoutine(Ex))可能非常有用。

#2


1  

here I found full code like @Martin Drab code

在这里,我找到了像@Martin Drab代码的完整代码

EDIT: new fixed code

编辑:新的固定代码

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

    // ...
}

#1


1  

You can use ZwQueryInformationProcess with the information class of 27. THe following code uses this routine to obtain the full image file name from process' handle.

您可以将ZwQueryInformationProcess与信息类27一起使用。以下代码使用此例程从进程'句柄获取完整的映像文件名。

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

You can obtain the process handle by the following ways:

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

  • ObOpenObjectByPointer, you need process' EPROCESS address (PsLookupProcessByProcessId may help).

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

  • ZwOpenProcess – youn need to know PID of the target process.

    ZwOpenProcess - 您需要知道目标进程的PID。

However, using this code in every invocation of your minifilter's pre/post callback can be quite time-consuming. I solve this problem by caching process names in a hash table that uses PID as a key. Notify routines (PsSetXXXNotifyRoutine(Ex)) may prove very useful when building and managing such a table.

但是,在每次调用minifilter的前/后回调时使用此代码可能非常耗时。我通过在使用PID作为键的哈希表中缓存进程名来解决此问题。在构建和管理这样的表时,通知例程(PsSetXXXNotifyRoutine(Ex))可能非常有用。

#2


1  

here I found full code like @Martin Drab code

在这里,我找到了像@Martin Drab代码的完整代码

EDIT: new fixed code

编辑:新的固定代码

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

    // ...
}