Lister les process utilisant une dll

Signaler
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009
-
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
-
Bonjour, j'aimerai obtenir tout les pids utilisant une dll que je connait d'avance, j'ai donc trouvé ce code:
http://www.cppfrance.com/code.aspx?ID=19391
Mais pas moyen d'isolé juste ce que je vaus, je sais que mais connaissance en win32 sont assez limité.

11 réponses

Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Salut,

Regarde ce thread (Le dernier post surtout).
Tout est basé sur CreateToolhelp32Snapshot, que ce soit la recherche des processus ou pour lister les modules (.dll, .exe...) de ces processus.
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009

J'ai fait ce code:
bool WINAPI DLLEjecteurW(DWORD dwPid,PWSTR szDLLPath)
{
/* Search address of module */
MODULEENTRY32W meModule;
meModule.dwSize = sizeof(meModule);
HANDLE hSnapshot = NULL;

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
if(hSnapshot == NULL)
return false;

/* Search the right modules of the process */
Module32FirstW(hSnapshot, &meModule);
do{
if((lstrcmpiW(meModule.szModule,szDLLPath) 0) || (lstrcmpiW(meModule.szExePath,szDLLPath) 0))break;
}while(Module32NextW(hSnapshot, &meModule));

/* Get handle of the process */
HANDLE hProcess;

hProcess = OpenProcess(PROCESS_ALL_ACCESS, false,dwPid);
if(hProcess == NULL)
{
CloseHandle(hSnapshot);
return false;
}

LPTHREAD_START_ROUTINE lpthThreadFunction;
/* Get addresse of FreeLibrary in kernel32.dll */
lpthThreadFunction = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary");
if(lpthThreadFunction == NULL)
{
CloseHandle(hProcess);
CloseHandle(hSnapshot);
return false;
}	

/* Creation the remote thread */
DWORD dwThreadID = 0;
HANDLE hThread = NULL;
hThread = CreateRemoteThread(hProcess, NULL, 0, lpthThreadFunction,meModule.modBaseAddr, 0, &dwThreadID);
if(hThread == NULL)
{
CloseHandle(hSnapshot);
CloseHandle(hProcess);
return false;
}

WaitForSingleObject(hThread,INFINITE);

CloseHandle(hProcess);
CloseHandle(hThread);

return true;
}

void HardUnloadDLL(QString myDllName)
{
//QFile theDllFile(myDllName);
//myDllName=theDllFile.fileName();
DEBUGCONSOLE(90,"HardUnloadDLL","start");
HANDLE hSnapShot1;
PROCESSENTRY32 uProcess;
HANDLE hSnapShot2;
MODULEENTRY32 me32;
QString DllLoaded = "";
QString DllLoadedName = "";
QString DllLoadedPath = "";
bool bResult;
bool r;
short NbProcess;
NbProcess=0;

hSnapShot1 = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);

uProcess.dwSize = (DWORD) sizeof(PROCESSENTRY32);

r = Process32First(hSnapShot1, &uProcess);

while ( r )
{
r = Process32Next(hSnapShot1, &uProcess);
QString myProcessName;
myProcessName=QString::fromWCharArray(uProcess.szExeFile);
if (uProcess.th32ProcessID < 99999)
{
hSnapShot2 = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, uProcess.th32ProcessID );
if ((int)hSnapShot2 != -1 )
{
me32.dwSize = sizeof(me32);
bResult = Module32First( hSnapShot2, &me32 );
while( bResult )
{
DllLoaded=QString::fromWCharArray(me32.szExePath);
DllLoadedName=QString::fromWCharArray(me32.szModule);
if (DllLoaded == myDllName)
{
DEBUGCONSOLE(90,"RegisterShellExtDll","The path: "+DllLoaded);
DEBUGCONSOLE(90,"RegisterShellExtDll",myProcessName+" ("+QString::number(uProcess.th32ProcessID)+")");
DLLEjecteurW(uProcess.th32ProcessID,me32.szExePath);
}
bResult = Module32Next( hSnapShot2, &me32 );
}
}
else
{
DEBUGCONSOLE(90,"HardUnloadDLL","(int)hSnapShot2 != -1 for "+myProcessName+" ("+QString::number(uProcess.th32ProcessID)+")");
}
if(hSnapShot2)
CloseHandle(hSnapShot2);
}
else
{
DEBUGCONSOLE(90,"HardUnloadDLL","uProcess.th32ProcessID > 99999 for "+myProcessName+" ("+QString::number(uProcess.th32ProcessID)+")");
}
}
CloseHandle(hSnapShot1);
}


Il marche pour:
les process 32Bits -> dll 32Bits
les process 64Bits -> dll 64Bits
Mais pas pour:
les process 64Bits -> dll 32Bits
Comment résourdre ce probléme?


Mon projet Qt: http://ultracopier-fr.first-world.fr/
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
64 bits ? C'est quoi ?

Franchement, je sais même pas comment peut fonctionner une dll 32 bits au sein d'un processus 64 bits. Genre une fonction de la dll prend en argument une chaîne. La chaîne est adressé en 64 bits dans le processus par l'appelant. Il faut cependant donner une adresse 32 bits à la dll... Chaud !

Breuh hum.
Au fait, tu as localisé ce qui coince ? C'est le FreeLibrary qui échoue ou c'est avant ?
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009

Non je n'est hélas pu localisé ou ça coince, (je pense que je suis trop limité coté windows).


Mon projet Qt: http://ultracopier-fr.first-world.fr/
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
C'est marrant, d'après cet article, c'est impossible de charger une dll 32 bits dans un process 64 bits. C'est vrai que ça me paraît bien aussi.

Et voilà une citation de SetWindowsHookEx :

SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.


Tu es sûr que c'est possible ?
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009

Mon but est de décharger un dll 32Bits d'un programme 32Bits depuis un programme 64Bits.
Ma dll est chargé avec sucés.
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
24
Pas de DLL 32 dans proces 64, c'est impossible.
En plus de la taille des params (adresses ou autres), le 64 bosse en fastcall alors que le 32 est en stdcall, ce serait badaboum au 1er appel de fonction.

ciao...
BruNews, MVP VC++
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009

Mon but est de décharger un dll 32Bits d'un programme 32Bits depuis un programme 64Bits.
Ma dll est chargé avec sucés.

Mon projet Qt: http://ultracopier-fr.first-world.fr/
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Ah ok ! Ca me rassure.

Bon par contre c'est normal que ton programme en 64 bits ne fonctionne pas sur une dll 32.

Sur cette ligne :
lpthThreadFunction = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary");

Tu récupère un handle sur kernel32 dans ton propre processus, donc sur une kernel32... 64 bits ! De même l'adresse de FreeLibrary que tu récupères est sur 64 bits.

Donc forcément, quand tu fait CreateRemoteThread, tu lui passe cette adresse sur 64 bits qui ne correspond à rien dans l'autre processus qui a un kernel32 32 bits, et qui en plus est dans un adressage 32 bits...

Même si tu ne peux pas passer physiquement d'adresse sur 32 bits à CreateRemoteThread, il est probable que l'on peut s'en servir en mettant une adresse de 32 bits dans les 32 bits de poids faible de l'adresse sur 64 bits attendue.

Par contre, faudrait que tu trouves l'adresse de FreeLibrary dans l'autre processus... Ce qui n'est pas évident ! Tu dois cependant pouvoir récupérer l'adresse de kernel32 avec CreateToolhelp32Snapshot (Comme tu l'as fait pour ta dll à décharger), ensuite utiliser ReadProcessMemory pour exploiter le header PE et ainsi déterminer l'adresse de FreeLibrary. Mais c'est quand même assez lourd...
Messages postés
134
Date d'inscription
vendredi 2 mai 2003
Statut
Membre
Dernière intervention
14 novembre 2009

Surtout que mes connaissances en win32 ce limite à prendre du code et à le modifié...
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Tu te sous-estimes ! C'est vraiment pas compliqué le Win32 : Suffit de connaître le C et d'aller lire la doc.

En plus, là, c'est pas du win32, c'est de la lecture + des maths niveau maternelle. Suffit de lire la doc de mon précédent lien et de faire des additions !

Voilà ce que ça me donne, mais pour un processus 32 bits récupérant l'adresse dans un processus 32 bits... J'ai utiliser des UINT, mais il reste quand même probablement des problèmes pour porter le code en 64 bits. Et il faudrait aussi du boulot pour le faire fonctionner sur un processus 64 bits, vu que c'est plus du PE (Du PE32+ ?).

#include <tchar.h>
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

/**
 * Affiche les infos sur la dernière erreur Win32
 */
DWORD __stdcall Sys_ShowLastError()
{
  DWORD nLastError;           /* Numéro de l'erreur                           */
  LPTSTR lpMessageBuffer;     /* Récupération du message                      */

  nLastError = GetLastError();

  /* Formatage du message */
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (void*)&lpMessageBuffer, 0, NULL);

  /* Affichage du message */
  MessageBox(NULL, lpMessageBuffer, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

/**
 * Renvoie l'adresse d'un module d'un autre processus
 */
HMODULE GetProcessModuleHandle(DWORD nProcessId, char* lpModuleName)
{
  HANDLE hModuleSnapshot;
  MODULEENTRY32 modulInfo;
  HMODULE hResult;

  hResult = NULL;

  /* Création du snapshot */
  hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, nProcessId);
  if (hModuleSnapshot == INVALID_HANDLE_VALUE) goto the_end;

  /* Parcours des modules */
  modulInfo.dwSize = sizeof(MODULEENTRY32);
  if (Module32First(hModuleSnapshot, &modulInfo))
  {
    do
    {
      if (! lstrcmp(lpModuleName, modulInfo.szModule))
      {
        hResult = (HMODULE)modulInfo.modBaseAddr;
        break;
      }
    } while (Module32Next(hModuleSnapshot, &modulInfo));
  }
  if (! hResult) SetLastError(126);

  CloseHandle(hModuleSnapshot);
the_end:
  return hResult;
}

/**
 * Lit une chaîne dans un autre processus
 */
BOOL __stdcall ReadProcessString(HANDLE hProcess, char* lpBuffer, char* lpStringAddress)
{
  BOOL bResult;
  int nI;

  bResult = FALSE;

  nI = -1;
  do
  {
    nI++;
    if (! ReadProcessMemory(hProcess, lpStringAddress + nI, &lpBuffer[nI], 1, NULL)) goto the_end;
  } while (lpBuffer[nI]);

  bResult = TRUE;

the_end:
  return bResult;
}

/**
 * Renvoie l'adresse d'une fonction d'un module d'un autre processus
 */
void* __stdcall GetProcessProcAddress(HANDLE hProcess, HMODULE hModule, char* lpProcName)
{
  char* lpBaseAddress;          /* Adresse de base de l'image distante        */
  UINT nOffset;                 /* Offset pour lecture                        */
  UINT nNumberOfNamePointers;   /* Nombre de symboles exportés                */
  UINT nStartingOrdinal;        /* Valeur de départ pour les ordinaux         */
  UINT nTableOffset;            /* Offset des différentes tables 
d'export     */
  UINT nSymbolNameOffset;       /* Offset du symbole exporté                  */
  char lpSymbolName[2048];      /* Symbole exporté                            */
  unsigned short nOrdinal;      /* Numéro ordinal du symbole recherché        */
  void* lpResult;
  int nI;

  lpResult = NULL;

  lpBaseAddress = (char*)hModule;

  /* L'offset du header PE est en 0x3C */
  nOffset = 0x3C;
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset, &nOffset, 4, NULL)) goto the_end;

  /* L'offset de la table d'export est en PE header + 4 (Signature) + 0x14 (Coff header) + 0x60 (Offset dans l'optional) */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 4 + 0x14 + 0x60, &nOffset, 4, NULL)) goto the_end;

  /* Récupération du nombre de symboles exportés */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 0x18, &nNumberOfNamePointers, 4, NULL)) goto the_end;

  /* Récupération de la valeur de départ pour les ordinaux */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 0x10, &nStartingOrdinal, 4, NULL)) goto the_end;

  /* Récupération de l'offset de la table des pointeurs sur les noms */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 0x20, &nTableOffset, 4, NULL)) goto the_end;

  /* Parcourt des symboles exportés */
  for (nI = 0; nI < nNumberOfNamePointers; nI++)
  {
    /* Récupération de l'adesse de la chaîne dans l'autre processus */
    if (! ReadProcessMemory(hProcess, lpBaseAddress + nTableOffset + 4 * nI, &nSymbolNameOffset, 4, NULL)) goto the_end;

    /* Récupération du symbole et comparaison */
    if (! ReadProcessString(hProcess, lpSymbolName, lpBaseAddress + nSymbolNameOffset)) goto the_end;
    if (! lstrcmp(lpSymbolName, lpProcName)) break;
  }
  
  /* Vérification qu'on a trouvé la procédure recherchée */
  if (nI == nNumberOfNamePointers)
  {
    SetLastError(127);
    goto the_end;
  }

  /* Récupération de l'offset sur la table des ordinaux */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 0x24, &nTableOffset, 4, NULL)) goto the_end;

  /* Récupération de l'ordinal */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nTableOffset + nI * 2, &nOrdinal, 2, NULL)) goto the_end;

  /* Les ordinaux sont stockés corrigés dans la table des ordinaux (http://www.bitsum.com/pedocerrors.htm) */
  nOrdinal += nStartingOrdinal;

  /* Récupération de l'offset sur la table d'export */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nOffset + 0x1C, &nTableOffset, 4, NULL)) goto the_end;

  /* Récupération de l'adresse */
  if (! ReadProcessMemory(hProcess, lpBaseAddress + nTableOffset + (nOrdinal - nStartingOrdinal) * 4, &nOffset, 4, NULL)) goto the_end;

  lpResult = lpBaseAddress + nOffset;

the_end:
  return lpResult;
}

int main()
{
  STARTUPINFO startupInfo;
  PROCESS_INFORMATION processInfo;
  HMODULE hMod;
  void* lpProc;
  int nResult;

  nResult = 0;
  
  ZeroMemory(&startupInfo, sizeof(startupInfo));
  startupInfo.cb = sizeof(startupInfo);
  startupInfo.dwFlags = STARTF_USESHOWWINDOW;
  startupInfo.wShowWindow = SW_SHOW;

  CreateProcess(NULL, "calc", NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);

  /* Très moche, mais la récupération d'un handle sur le process est pas le sujet */
  Sleep(500);

  hMod = GetProcessModuleHandle(processInfo.dwProcessId, "kernel32.dll");
  if (! hMod)
  {
    nResult = Sys_ShowLastError();
    goto the_end;
  }
  printf("Remote module address: %#08x\n", (unsigned int)hMod);

  lpProc = GetProcessProcAddress(processInfo.hProcess, hMod, "FreeLibrary");
  if (! lpProc)
  {
    nResult = Sys_ShowLastError();
    goto the_end;
  }
  printf("Remote proc address: %#08x\n", (unsigned int)lpProc);

the_end:
  CloseHandle(processInfo.hThread);
  CloseHandle(processInfo.hProcess);
  return nResult;
}