I am developing my own driver.

How to get the process ID, knowing only its name? It is necessary on C, not C ++

OS Windows 7, driver type - intranuclear.

  • What is the operating system and its version? What type of driver - user mode or intranuclear? - ߊߚߤߘ
  • Windows 7, intranuclear - Vitali

2 answers 2

The Windows Driver API does not provide any way to directly obtain a process identifier (PID) by its name, or even the ability to enumerate all processes in the system.

Therefore, we will have to independently maintain the associative array “Process Name - PID” and update it in a timely manner.

The update is performed using PsSetCreateProcessNotifyRoutine , which allows you to track the creation and destruction of processes.

Associative array, you should use your own. It doesn't matter if it is based on a linked list, grouped by hashes, or something else, I’ll just introduce some MAP_ADD and MAP_REMOVE to add and remove items, respectively.

Then we get about the following code:

  • Interception registration (perform in DriverEntry ):

     PsSetCreateProcessNotifyRoutine(NotifyRoutine, FALSE); 
  • Unregister capture (run in DRIVER_OBJECT::DriverUnload ):

     PsSetCreateProcessNotifyRoutine(NotifyRoutine, TRUE); 
  • Processing the actual capture:

     static void NotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create) { NTSTATUS Status; // Получаем PID из описателя PEPROCESS Process; Status = ObReferenceObjectByHandle( ProcessId, PROCESS_QUERY_INFORMATION, PsProcessType, PreviousMode, (PVOID*)&Process, NULL ); if(NT_SUCCESS(Status)) { // Получаем указатель на имя процесса. PUNICODE_STRING ProcessName; Status = SeLocateProcessImageName(ProcessName, Process); if(NT_SUCCESS(Status)) { if(Create == TRUE) // Если создан новый процесс MAP_ADD(ProcessName, ProcessId); else // Если процесс уничтожен MAP_REMOVE(ProcessName); } // Уменьшаем счётчик ссылок на процесс, иначе у пользователя образуется // большое количество неубиваемых процессов. ObDereferenceObject(Process); } } 

Important note: I do not have any experience in driver writing, all of the above was obtained as a result of studying MSDN and ReactOS source codes.

  • And if the process was started before the driver started? - Vitali
  • wininit , wininit , the root of the hierarchy of user processes, runs after all Reinitialize have been Reinitialize . So no user process will be missed; I don’t know about system (like System ). - ߊߚߤߘ
  • For now, I CreateToolhelp32Snapshot / Process32First / Process32Next bundle works at a low level, with which it Process32Next processes in the Win32 subsystem . I will finish - I will publish the second answer. - ߊߚߤߘ
  • Understood. See the second answer (DDK is not at hand, check operation, again, there is no possibility). - ߊߚߤߘ

There is no ready-made function for getting the PID by the process name, but you can manually go through the linked list of processes.

 HANDLE getPidByName(PCUNICODE_STRING name) { NTSTATUS Status; // Отладочная метка для области памяти с копией списка процессов. Пусть будет "PrcL" // Так как у нас LittleEndian, то первая буква находится в старшем байте. #define MEM_TAG ('P' << 24 | 'r' << 16 | 'c' << 8 | 'L') // Мы не можем заранее узнать размер буфера, поэтому будем подбирать // экспериментальным путём, увеличивая при каждой неудаче на размер страницы (4КБ). // Судя по тому, что так делает даже CreateToolhelp32Snapshot(), это нормальная // практика. PVOID ProcThrdInfo; SIZE_T ProcThrdInfoSize = 0; do { // Буферы размером больше PAGE_SIZE выделяются в отдельных страницах, поэтому // фрагментация кучи нам не грозит. ProcThrdInfoSize += PAGE_SIZE; ProcThrdInfo = ExAllocatePoolWithTag(PagedPool, ProcThrdInfoSize, MEM_TAG); if(ProcThrdInfo) { // Получаем копию списка процессов. Принимающий буфер расположен // в пространстве ядра, поэтому вызываем Zw-версию функции, не выполняющую // проверок указателей. Status = ZwQuerySystemInformation( SystemProcessInformation, &ProcThrdInfo, &ProcThrdInfoSize, NULL ); if(!NT_SUCCESS(Status)) ExFreePoolWithTag(ProcThrdInfo, MEM_TAG); } } while(ProcThrdInfo && Status == STATUS_INFO_LENGTH_MISMATCH); if(ProcThrdInfo) { if(NT_SUCCESS(Status)) { PSYSTEM_PROCESS_INFORMATION ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; // Перебираем записи, пока не найдём ту, что с искомым именем ULONG ProcOffset = 0; HANDLE FoundHandle = 0; do { ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) ((ULONG_PTR)ProcessInfo + ProcOffset); if(RtlCompareUnicodeString(ProcessInfo->ImageName, name, FALSE) == 0) FoundHandle = ProcessInfo->UniqueProcessId; ProcOffset = ProcessInfo->NextEntryOffset; } while(FoundHandle == 0 && ProcOffset != 0) ExFreePoolWithTag(ProcThrdInfo, MEM_TAG); return FoundHandle; } else { // Непредвиденная ошибка у ZwQuerySystemInformation(). См. Status // для получения подробной информации. return 0; } else { // Не хватило памяти return 0; } } 

If ProcessInfo->ImageName unavailable ( correctly starting with some version of Windows ), try replacing it with the trinity of PsLookupProcessByProcessId() + PsGetProcessImageFileName() + ObDereferenceObject() .

  • Swears at the ObReferenceObjectByHandle function arguments, although the corresponding library is connected to PSYSTEM_PROCESS_INFORMATION, and also connected the corresponding library, but the compiler swears to PSYSTEM_PROCESS_INFORMATION - Vitali
  • @ Vitali, what is the text of the error? And look, please, from where ObReferenceObjectByHandle came from, because in the above code it is not (at least explicitly). - ߊߚߤߘ