vendredi 1 février 2008

Récupérer le PID d'un process

Bon alors aujourd'hui on va voir une alternative aux fameux Process32First()/Process32Next() que je vois très souvent dans les codes pour faire une liste des process ou alors pour rechercher un process dans les process en execution et que je commenterais pas ici car il y a des articles très bien partout sur le net.

Pour un exemple de code regarder ici : http://akhenathon2.free.fr/coding/ProcessNameToPid.c

Bon je vois toujours cette méthode qui consiste à faire une boucle sur Process32Next() pour avoir une liste des process et ensuite vérifier si le szExeFile du process correspond au nom du process qu'on cherche.

Bon les code se ressembleront un peu cependant on va utiliser une fonction qui nous renvoie une liste de PID ( les PID des process en execution ).

Allez c'est parti pour la chasse au PID. On va donc utiliser la fonction EnumProcesses() qui nous renvoie comme promis une liste de PID ainsi que le nombre de process en execution ( il faudra faire une petit opération pour l'avoir ).

Bon comme d'hab on va voir la doc msdn : http://msdn2.microsoft.com/en-us/library/ms682629(VS.85).aspx

Voici le prototype de la fonction EnumProcesses() :
BOOL WINAPI EnumProcesses(
__out DWORD* pProcessIds,
__in DWORD cb,
__out DWORD* pBytesReturned
);

Il nous faut donc un tableau de DWORD qui recevra la liste des PID ainsi qu'un DWORD qui recevra le nombre de bytes retournés, il suffira de le divisé par la taille d'un DWORD pour obtenir le nombre de process en execution.
Alors attention, le tableau doit être assez grand pour recevoir tout les PID j'ai choisi de faire un tableau à 128 entrée mais après a vous de juger le nombre de PID qu'il est sensé y avoir ( avec 128 on a quand même une bonne marge ).
#include <windows.h>
#include <psapi.h>

int main(void)
{
DWORD ListProcess[128], nProcess;

EnumProcesses(ListProcess, sizeof(ListProcess),
&nProcess);
nProcess /= sizeof(DWORD);

/* ... */

return 0;
}


Bon alors maintenant qu'on a la liste des process, il faut récupérer le nom des process pour pouvoir les comparer avec le process qu'on recherche.

Pour ce faire on va utiliser une combinaison des fonctions OpenProcess() ( pour récupérer un handle sur le process ) puis EnumProcessModules() qui nous renverra la liste des module du process et on a des la chance parce que le premier module est le process lui même ensuite suffira de faire un GetModuleBaseName() pour récupérer son nom.

Ici je vais juste faire une liste des process ( je mettrais à la fin quelques codes ).
#include <windows.h>
#include <psapi.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
DWORD ListProcess[128], nProcess;
size_t i;

EnumProcesses(ListProcess, sizeof(ListProcess),
&nProcess);
nProcess /= sizeof(DWORD);

for(i=0;i<nProcess;i++)
{
char szProcessName[MAX_PATH];
HANDLE hProcess=OpenProcess(PROCESS_VM_READ
|PROCESS_QUERY_INFORMATION,
FALSE, ListProcess[i]);

if(hProcess)
{
HMODULE hMod;
DWORD unused;

if(EnumProcessModules(hProcess, &hMod,
sizeof(hMod), &unused))
{
GetModuleBaseName(hProcess, hMod,
szProcessName,
sizeof(szProcessName)/sizeof(char));
printf("[+]ProcessName: %s\tPID: %lu\n",
szProcessName,
ListProcess[i]);
}
}
CloseHandle(hProcess);
}

return 0;
}


Ensuite en modifiant juste le HMODULE en un tableau assez grand vous pourrez récupérer tous les modules du process.

Et donc voici comme promis quelques petits code :
-> ProcessNameToPidWithEnumProcesses.c
-> ListModuleInProcess.c

Have fun :)

PS : N'oubliez pas de linker la lib psapi

Références :

EnumProcesses --> http://msdn2.microsoft.com/en-us/library/ms682629(VS.85).aspx
OpenProcess --> http://msdn2.microsoft.com/en-us/library/ms684320(VS.85).aspx
EnumProcessModules --> http://msdn2.microsoft.com/en-us/library/ms682631(VS.85).aspx
GetModuleBaseName --> http://msdn2.microsoft.com/en-us/library/ms683196(VS.85).aspx

Aucun commentaire: