2009-02-28 17 views
10

¿Cómo determinar de qué DLL depende un binario al usar métodos programáticos?Cómo determinar las dependencias DLL de ejecutables de Windows programáticamente?

Para ser claros, no estoy tratando de determinar las dependencias de la DLL del ejecutor en ejecución, sino de cualquier ejecutor arbitrario (que puede faltar una DLL requerida). Estoy buscando una solución para implementar en una aplicación C/C++. Esto es algo que debe hacer mi aplicación en tiempo de ejecución y no puede hacerlo una aplicación de terceros (como depende).

+0

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

Respuesta

9

Eche un vistazo a la API IMAGE_LOAD_FUNCTION. Devolverá un puntero a una estructura LOADED_IMAGE, que puede usar para acceder a las diversas secciones de un archivo PE.

Puede encontrar algunos artículos que describen cómo se estructuran las estructuras here y here. Puede descargar el código fuente de los artículos here.

Creo que esto debería darle todo lo que necesita.

Actualización:

que acaba de descargar el código fuente del artículo. Si abre EXEDUMP.CPP y echa un vistazo a DumpImportsSection debe tener el código que necesita.

+0

Gracias por su sugerencia. Especialmente para los enlaces a los ejemplos fuente. Exactamente lo que estaba buscando. –

6

Eso no es posible de determinar. Al menos no sin mucho trabajo. Cualquier binario puede llamar a LoadLibrary para cargar una DLL. Incluso si escanearas el código de todas las llamadas a LoadLibrary, tendrías que determinar qué cadenas se usaban para identificar la biblioteca. Rastrear dónde en la memoria dinámica se colocó la cuerda va a ser más difícil de lo que quiere abordar.

+1

¿Por qué votarme aquí? Esta respuesta es técnicamente precisa por lo que puedo decir. –

+0

Supongo por qué esta respuesta fue rechazada: no distingue entre dependencias implícitas (que pueden determinarse, consulte el enlace de alex2k8) y dependencias explícitas (que es de lo que está hablando). No seas triste, ¡la respuesta fue a medias! – jdigital

+0

@jdigital: Esta respuesta no es ni la mitad de lo correcta. Es la respuesta correcta a una pregunta, solicitando encontrar programáticamente todas las dependencias de una imagen ejecutable. La pregunta es preguntar por el caso general, por lo que debe tener en cuenta la vinculación dinámico en tiempo de ejecución, utilizando 'LoadLibrary', o los módulos que se cargan implícitamente al crear una instancia de un objeto COM. Dependency Walker tiene un modo de creación de perfiles, que intenta contabilizar binarios, que se cargan en tiempo de ejecución, pero no se puede garantizar una cobertura de código del 100%, por lo que incluso ese intento no funcionará. Nos guste o no, esta es la respuesta correcta. – IInspectable

1

En pocas palabras, debe escanear la sección de las importaciones del archivo PE para cada DLL utilizada por el archivo ejecutable. Luego ubique y escanee de forma recursiva cada dll hasta que encuentre todas las dependencias.

Por supuesto, las aplicaciones pueden usar la familia de funciones LoadLibrary para funcionalidad requerida u opcional. Eso no será detectado con este método.

-1

¡Por supuesto que es posible y fácil! Es incluso un Win32 FAQ para las edades de Win32 api Group

=> unas pocas líneas de código con DBAPIs

0

¿Qué tal un DLL que se puede llamar para calcular toda esta información para usted y pasar de nuevo la respuesta como una matriz de CStrings?

PE Format DLL puede hacer esto por usted. Suministrado con código fuente, sin restricciones de GPL. PE File Explorer es una aplicación GUI que usa la DLL, también se suministra con la fuente (sin GPL).

4

76 líneas de hacerlo sobre la base de pedump código (no se olvide de añadir Imagehlp.lib como dependencia):

#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 puede hacer esto usando el menú de perfil, si usted tiene un archivo ejecutable de destino . Simplemente cargue el ejecutable, dígale que empiece a crear perfiles, y listará todos los módulos cargados mientras ejecuta el programa.

Dependency Walker FAQ (first question...)

+0

La creación de perfiles solo permite cargar los módulos que desencadena. A menos que pueda garantizar una cobertura de código del 100%, no puede estar seguro de encontrar todas las dependencias. Y luego también verá que se cargan los módulos, que no son estrictamente necesarios para su programa (por ejemplo, extensiones de shell al abrir un cuadro de diálogo Guardar archivo). – IInspectable

Cuestiones relacionadas