Как программно определить зависимости DLL от исполняемых файлов Windows?

Как определить, какая DLL-библиотека зависит от использования программных методов?

Чтобы быть ясным, я не пытаюсь определить зависимости DLL от исполняемого exec, но от любого произвольного exec (для которого может отсутствовать требуемая DLL). Я ищу решение для реализации в приложении C/С++. Это то, что должно выполняться моим приложением во время выполнения и не может быть выполнено сторонним приложением (например, зависит).

Ответ 1

Взгляните на IMAGE_LOAD_FUNCTION API. Он вернет указатель на структуру LOADED_IMAGE, которую вы можете использовать для доступа к различным разделам PE файла.

Вы можете найти некоторые статьи, описывающие, как структуры размещаются здесь, и . Вы можете загрузить исходный код для статей здесь.

Я думаю, что это должно дать вам все, что вам нужно.

Update:

Я только что загрузил исходный код для статьи. Если вы откроете EXEDUMP.CPP и взгляните на DumpImportsSection, он должен иметь код, который вам нужен.

Ответ 2

Это невозможно определить. По крайней мере, не без большой работы. Любой двоичный файл может вызвать LoadLibrary для загрузки DLL. Даже если вы должны были сканировать код для всех вызовов в LoadLibrary, вам нужно будет определить, какие строки использовались для идентификации библиотеки. Отслеживание там, где в динамической памяти помещена строка, будет сложнее, чем вы хотите решить.

Ответ 3

76 строк для этого на основе pedump code (не забудьте добавить Imagehlp.lib в качестве зависимости):

#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 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;
}

Ответ 4

В двух словах вам нужно отсканировать файл импорта файла PE для каждой DLL, используемой исполняемым файлом. Затем рекурсивно найдите и сканируйте каждую dll, пока не найдете все зависимости.

Конечно, приложения могут использовать семейство функций LoadLibrary для требуемых или дополнительных функций. Это не будет обнаружено с помощью этого метода.

Ответ 5

Dependency Walker может сделать это, используя меню профиля, если у вас есть целевой исполняемый файл. Просто загрузите исполняемый файл, скажите ему, чтобы начать профилирование, и он перечислит все модули, загруженные во время выполнения программы.

Часто задаваемые вопросы по Walker (первый вопрос...)

Ответ 6

Как насчет DLL, которую вы можете вызвать, чтобы рассчитать всю эту информацию для вас и передать ответ в виде массива CStrings?

PE Format DLL может сделать это за вас. Поставляется с исходным кодом, без ограничений GPL. PE File Explorer - это графическое приложение, использующее DLL, также поставляемое с источником (без GPL).

Ответ 7

Конечно, это возможно и легко! Это даже часто задаваемые вопросы по Win32 на Win32 api Group

= > несколько строк кода с помощью DBAPI