4

Je dois obtenir par programme la liste des dépendances de DLL. Voici comment j'essaie de résoudre cette tâche:C++: obtenir des dépendances dll natives sans le charger en cours

BSTR GetDllDependencies(const wchar_t* dllPath) 
{ 
    std::wstring dependencies; 

    struct LibDeleter 
    { 
     typedef HMODULE pointer; 
     void operator()(HMODULE hMod) { FreeLibrary(hMod); } 
    }; 

    auto hModRaw = LoadLibraryExW(dllPath, NULL, DONT_RESOLVE_DLL_REFERENCES); //(*)nullptr nere 
    auto hMod = std::unique_ptr<HMODULE, LibDeleter>(); 

    auto imageBase = (DWORD_PTR)hMod.get(); 

    auto header = ImageNtHeader(hMod.get()); 
    auto importRVA = header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 
    auto importTable = (PIMAGE_IMPORT_DESCRIPTOR)(DWORD_PTR)(importRVA + imageBase); 

    while (importRVA && importTable->OriginalFirstThunk) 
    { 
     auto importedModuleName = (char*)(DWORD_PTR)(importTable->Name + imageBase); 
     dependencies 
      .append(importedModuleName, importedModuleName + std::strlen(importedModuleName)) 
      .append(L","); 

     importTable++; 
    } 

    auto result = SysAllocString(dependencies.c_str()); 

    return result; 
} 

Cela fonctionne. Mais, comme vous pouvez le voir, il charge la DLL dans le processus. Et j'ai rencontré un problème dans cet endroit: LoadLibraryEx renvoie nullptr si le processus a déjà chargé DLL avec le même nom.

nullptr

Je ne suis pas sûr qu'il est autorisé à charger deux DLL avec le même nom (mais emplacement différent) dans le même processus? Je crois oui. Alors pourquoi LoadLibraryEx renvoie nullptr? Est-il possible d'obtenir en quelque sorte des dépendances DLL sans chargement de DLL?

+0

Vous devez analyser la section des importations du fichier PE (Portable Executable) (c'est-à-dire .dll ou .exe). – VTT

+0

Comme mentionné dans la documentation ['DONT_RESOLVE_DLL_REFERENCES' est obsolète et ne peut pas être pris en charge dans toutes les versions de Windows] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179 (v = vs. 85) .aspx), vous devrez charger en tant que fichier de données à la place. – Mgetz

+0

'LoadLibraryEx renvoie nullptr si le processus a déjà chargé la DLL avec le même nom'. – RbMm

Répondre

0

Cette solution utilise la navigation manuel dans le fichier DLL. La base de la solution est la fonction RVAtoRAW qui traduit les adresses RVA en RAW (adresses dans le fichier).

//Defining in which section particular RVA address actually located (section number) 
DWORD RVAtoRAW(DWORD rva, PIMAGE_SECTION_HEADER sectionHeaderRAW, WORD sectionsCount) 
{ 
    int sectionNo; 
    for (sectionNo = 0; sectionNo < sectionsCount; ++sectionNo) 
    { 
     auto sectionBeginRVA = sectionHeaderRAW[sectionNo].VirtualAddress; 
     auto sectionEndRVA = sectionBeginRVA + sectionHeaderRAW[sectionNo].Misc.VirtualSize; 
     if (sectionBeginRVA <= rva && rva <= sectionEndRVA) 
      break; 
    } 
    //Evaluating RAW address from section & RVA 
    auto sectionRAW = sectionHeaderRAW[sectionNo].PointerToRawData; 
    auto sectionRVA = sectionHeaderRAW[sectionNo].VirtualAddress; 
    auto raw = sectionRAW + rva - sectionRVA; 

    return raw; 
} 

BSTR GetDllDependencies(const wchar_t* dllPath) 
{ 
    auto buffer = ReadFile(dllPath); 
    if (buffer.empty()) 
     return SysAllocString(L""); 

    //RAW - offset from beginnig of the file (absolute "address" within file) 
    auto baseRAW = buffer.data(); 
    auto dosHeaderRAW = (PIMAGE_DOS_HEADER)baseRAW; 
    auto peHeaderRAW = (PIMAGE_NT_HEADERS)(baseRAW + dosHeaderRAW->e_lfanew); 
    auto sectionHeaderRAW = (PIMAGE_SECTION_HEADER)(baseRAW + dosHeaderRAW->e_lfanew + sizeof(IMAGE_NT_HEADERS)); 

    auto sectionsCount = peHeaderRAW->FileHeader.NumberOfSections; 

    //RVA - Relative Virtual Address - relative (to ImageBase) address within virtual address space of the process which loads this DLL 
    auto importTableRVA = peHeaderRAW->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 
    auto importTableRAW = RVAtoRAW(importTableRVA, sectionHeaderRAW, sectionsCount); 
    auto importTable = (PIMAGE_IMPORT_DESCRIPTOR)(baseRAW + importTableRAW); 

    std::wstring dependencies; 
    while (importTableRVA && importTable->OriginalFirstThunk) 
    { 
     auto nameRAW = RVAtoRAW(importTable->Name, sectionHeaderRAW, sectionsCount); 

     auto importedModuleName = (char*)(DWORD_PTR)(nameRAW + baseRAW); 
     dependencies 
      .append(importedModuleName, importedModuleName + std::strlen(importedModuleName)) 
      .append(L","); 

     importTable++; 
    } 

    auto result = SysAllocString(dependencies.c_str()); 

    return result; 
}