2009-02-28 7 views
10

Come determinare quale DLL è un binario dipende dall'utilizzo di metodi programmatici?Come determinare le dipendenze DLL eseguibili di Windows in modo programmatico?

Per essere chiari, non sto cercando di determinare le dipendenze DLL dell'esecuzione in esecuzione, ma di qualsiasi exec arbitrario (che potrebbe mancare una DLL richiesta). Sto cercando una soluzione da implementare in un'applicazione C/C++. Questo è qualcosa che deve essere fatto dalla mia applicazione in fase di runtime e non può essere fatto da un'app di terze parti (come dipende).

+0

Scegli questa [domanda] (http://stackoverflow.com/questions/362560/how-do-i-detect-the-dlls-required-by-an-application). – alex2k8

risposta

9

Dai uno sguardo all'API IMAGE_LOAD_FUNCTION. Restituirà un puntatore a una struttura LOADED_IMAGE, che è possibile utilizzare per accedere alle varie sezioni di un file PE.

È possibile trovare alcuni articoli che descrivono come sono strutturate le strutture here e here. È possibile scaricare il codice sorgente per gli articoli here.

Penso che questo dovrebbe darvi tutto il necessario.

Aggiornamento:

Ho appena scaricato il codice sorgente per l'articolo. Se apri EXEDUMP.CPP e dai un'occhiata a DumpImportsSection dovrebbe avere il codice che ti serve.

+0

Grazie per il suggerimento. Soprattutto per i collegamenti agli esempi di origine. Esattamente quello che stavo cercando. –

6

Questo non è possibile determinare. Almeno non senza un sacco di lavoro. Qualsiasi binario può chiamare LoadLibrary per caricare una DLL. Anche se dovessi eseguire la scansione del codice per tutte le chiamate a LoadLibrary, dovresti determinare quali stringhe sono state utilizzate per identificare la libreria. Rintracciare il punto in cui nella memoria dinamica è stata posizionata la stringa sarà più difficile di quanto si voglia affrontare.

+1

Perché votarmi qui? Questa risposta è tecnicamente accurata per quanto posso dire. –

+0

La mia ipotesi sul perché questa risposta è stata respinta: non fa distinzione tra le dipendenze implicite (che possono essere determinate, vedi il link di alex2k8) e le dipendenze esplicite (che è ciò di cui stai parlando). Non essere triste, la risposta era a metà! – jdigital

+0

@jdigital: questa risposta non è giusta. È la risposta corretta a una domanda, chiedendo di trovare a livello di codice tutte le dipendenze di un'immagine eseguibile. La domanda è la richiesta del caso generale, quindi è necessario tenere conto del collegamento dinamico di runtime, usando 'LoadLibrary', o moduli che sono implicitamente caricati, quando si crea un'istanza di un oggetto COM. Dependency Walker ha una modalità di profilazione, che tenta di tenere conto dei binari, che vengono caricati in fase di runtime, ma non è possibile garantire una copertura del codice al 100%, quindi anche questo tentativo non verrà eseguito. Piaccia o no, questa è la risposta corretta. – IInspectable

1

In breve, è necessario eseguire la scansione della sezione di importazione del file PE per ogni DLL utilizzata dal file eseguibile. Quindi individua ricorsivamente e scansiona ogni DLL finché non trovi tutte le dipendenze.

Ovviamente, le app possono utilizzare la famiglia di funzioni LoadLibrary per le funzionalità richieste o facoltative. Questo non verrà rilevato con questo metodo.

-1

Ovviamente è possibile e facile! E 'ancora un Win32 FAQ per le età su Win32 api Group

=> un paio di righe di codice con DBAPIs

0

Che ne dite di una DLL che è possibile chiamare per calcolare tutte queste informazioni per voi e per passare di nuovo la risposta come un array di CStrings?

PE Format DLL può farlo per voi. Fornito con codice sorgente, senza restrizioni GPL. PE File Explorer è un'applicazione GUI che utilizza la DLL, fornita anche con sorgente (senza licenza GPL).

4

76 linee di farlo sulla base di pedump codice (non dimenticare di aggiungere Imagehlp.lib come dipendenza):

#include <stdio.h> 
#include "windows.h" //DONT REMOVE IT 
#include "ImageHlp.h" 
#include "stdafx.h" 

template <class T> PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, T* pNTHeader) // 'T' == PIMAGE_NT_HEADERS 
{ 
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); 
    unsigned i; 

    for (i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++) 
    { 
     // This 3 line idiocy is because Watcom's linker actually sets the 
     // Misc.VirtualSize field to 0. (!!! - Retards....!!!) 
     DWORD size = section->Misc.VirtualSize; 
     if (0 == size) 
      size = section->SizeOfRawData; 

     // Is the RVA within this section? 
     if ((rva >= section->VirtualAddress) && 
      (rva < (section->VirtualAddress + size))) 
      return section; 
    } 

    return 0; 
} 

template <class T> LPVOID GetPtrFromRVA(DWORD rva, T* pNTHeader, PBYTE imageBase) // 'T' = PIMAGE_NT_HEADERS 
{ 
    PIMAGE_SECTION_HEADER pSectionHdr; 
    INT delta; 

    pSectionHdr = GetEnclosingSectionHeader(rva, pNTHeader); 
    if (!pSectionHdr) 
     return 0; 

    delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData); 
    return (PVOID) (imageBase + rva - delta); 
} 


void DumpDllFromPath(wchar_t* path) { 
    char name[300]; 
    wcstombs(name,path,300); 

    PLOADED_IMAGE image=ImageLoad(name,0); 

    if (image->FileHeader->OptionalHeader.NumberOfRvaAndSizes>=2) { 
     PIMAGE_IMPORT_DESCRIPTOR importDesc= 
      (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(
       image->FileHeader->OptionalHeader.DataDirectory[1].VirtualAddress, 
       image->FileHeader,image->MappedAddress); 
     while (1) 
     { 
      // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR 
      if ((importDesc->TimeDateStamp==0) && (importDesc->Name==0)) 
       break; 

      printf(" %s\n", GetPtrFromRVA(importDesc->Name, 
              image->FileHeader, 
              image->MappedAddress)); 
      importDesc++; 
     } 
    } 
    ImageUnload(image); 

} 

//Pass exe or dll as argument 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    DumpDllFromPath(argv[1]); 

    return 0; 
} 
1

Dependency Walker può farlo utilizzando il menu profilo, se si dispone di un eseguibile di destinazione . Carica semplicemente il file eseguibile, dillo per iniziare il profiling, e ti indicherà tutti i moduli caricati durante l'esecuzione del programma.

Dependency Walker FAQ (first question...)

+0

Il profilo vede solo il caricamento di quei moduli, che si attivano. A meno che tu non possa garantire una copertura del 100% del codice, non puoi essere sicuro di trovare tutte le dipendenze. E poi vedrai anche i moduli che vengono caricati, che non sono strettamente richiesti dal tuo programma (ad esempio le estensioni della shell quando apri una finestra di dialogo Salva file). – IInspectable

Problemi correlati