2016-09-06 8 views
1

В драйвере фильтра я могу позвонить IoGetCurrentProcess, чтобы получить структуру PEPROCESS, а не позвонить PsGetProcessImageFileName, чтобы получить имя файла.Как получить полное имя файла образа процесса в драйвере фильтра?

Мои вопросы: как я могу получить полный имя файла образа процесса?

+0

Связанные ссылка http://www.osronline.com/showThread.cfm?link=109252 –

+0

Это похоже на вопрос о winapi. Если это так, то, безусловно, это также вопрос на C++ (если какой-либо специфический для каждого языка тег является релевантным), а не вопрос C. Обновите теги соответствующим образом. –

+0

драйвер фильтра Я могу писать в C не на C++. – codeDom

ответ

1

here я нашел полный код, как @Martin Drab код

EDIT: новый фиксированный код

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

Код, кажется, теряет ручку процесса. –

+0

Утечка исправлена. – codeDom

+1

Нет. Я вижу коды кода, которые не закрывают дескриптор. Когда выделение буфера выходит из строя или когда первый вызов 'ZwQueryInformationProcess' возвращает что-то отличное от STATUS_INFO_LENGTH_MISMATCH. Некоторые другие пути ошибок, похоже, не обрабатываются правильно (если 'MmGetSystemRoutineAddress' не удается получить адрес' ZwQueryInformationProcess', если 'PsLookupProcessByProcessId' терпит неудачу ...). Некоторые из них приводят к возврату кода ошибки NTSTATUS, но я думаю, что это скорее удачное совпадение, чем у автора. –

1

Вы можете использовать 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; 
} 

Вы можете получить дескриптор процесса следующими способами:

  • ObOpenObjectByPointer, необходимо процесс EPROCESS адрес (PsLookupProcessByProcessId может помочь).

  • ZwOpenProcess - Вам необходимо знать PID целевого процесса.

Однако использование этого кода при каждом вызове обратного вызова вашего мини-фильтра может быть довольно трудоемким. Я решаю эту проблему, кэшируя имена процессов в хеш-таблице, которая использует PID в качестве ключа. Запросы уведомлений (PsSetXXXNotifyRoutine(Ex)) могут оказаться очень полезными при создании и управлении такой таблицей.