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

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

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

Ответы [ 6 ]

10 голосов
/ 28 февраля 2009

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

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

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

Обновление:

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

7 голосов
/ 22 ноября 2010

76 строк для этого на основе pedump кода (не забудьте добавить 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'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;
}
6 голосов
/ 28 февраля 2009

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

1 голос
/ 08 мая 2012

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

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

1 голос
/ 28 февраля 2009

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

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

0 голосов
/ 09 апреля 2010

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

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

...