如何以编程方式确定 Windows 可执行文件的 DLL 依赖项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/597260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:04:33  来源:igfitidea点击:

How to determine a windows executables DLL dependencies programmatically?

c++windowsdlldependenciesexecutable

提问by

How to determine what DLL's a binary depends on using programmatic methods?

如何使用编程方法确定二进制文件的 DLL 是什么?

To be clear, I am not trying to determine the DLL dependencies of the running exec, but of any arbitrary exec (that may be missing a required DLL). I'm looking for a solution to implement in a C/C++ application. This is something that needs to be done by my application at runtime and can't be done by a third party app (like depends).

需要明确的是,我不是要确定正在运行的 exec 的 DLL 依赖项,而是要确定任何任意 exec(可能缺少所需的 DLL)的 DLL 依赖项。我正在寻找在 C/C++ 应用程序中实现的解决方案。这是需要由我的应用程序在运行时完成的事情,而不能由第三方应用程序(如依赖)完成。

采纳答案by Scott Wisniewski

Take a look at the IMAGE_LOAD_FUNCTIONAPI. It will return a pointer to a LOADED_IMAGEstructure, which you can use to access the various sections of a PE file.

看看IMAGE_LOAD_FUNCTIONAPI。它将返回一个指向LOADED_IMAGE结构的指针,您可以使用它来访问 PE 文件的各个部分。

You can find some articles that describe how the structures are laid out here, and here. You can download the source code for the articles here.

您可以在此处此处找到一些描述结构布局方式的文章。您可以在此处下载文章的源代码。

I think this should give you everything you need.

我认为这应该给你你需要的一切。

Update:

更新:

I just downloaded the source code for the article. If you open up EXEDUMP.CPPand take a look at DumpImportsSectionit should have the code you need.

我刚刚下载了这篇文章的源代码。如果你打开EXEDUMP.CPP看看DumpImportsSection它应该有你需要的代码。

回答by Steve Rowe

That's not possible to determine. At least not without a whole lot of work. Any binary can call LoadLibrary to load a DLL. Even if you were to scan the code for all calls to LoadLibrary, you would have to determine what strings were being used to ID the library. Tracking down where in dynamic memory the string has been placed is going to be harder than you want to tackle.

这是无法确定的。至少不是没有大量的工作。任何二进制文件都可以调用 LoadLibrary 来加载 DLL。即使您要扫描所有对 LoadLibrary 的调用的代码,您也必须确定使用哪些字符串来标识库。追踪字符串在动态内存中的位置将比您想要解决的更难。

回答by benerone

76 lines to do that based on pedumpcode (don't forget to add Imagehlp.lib as dependancy):

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

回答by squeegee

Dependency Walkercan do this by using the profile menu, if you have a target executable. Simply load the executable, tell it to start profiling, and it'll list all the modules loaded while executing the program.

如果您有目标可执行文件,Dependency Walker可以使用配置文件菜单执行此操作。只需加载可执行文件,告诉它开始分析,它就会列出执行程序时加载的所有模块。

Dependency Walker FAQ (first question...)

Dependency Walker 常见问题解答(第一个问题...)

回答by zildjohn01

In a nutshell, you need to scan the PE file's imports sectionfor each DLL used by the executable. Then recursively locate and scan each dll until you've found all the dependencies.

简而言之,您需要为可执行文件使用的每个 DLL扫描 PE 文件的导入部分。然后递归定位并扫描每个 dll,直到找到所有依赖项。

Of course, apps can use the LoadLibrary family of functions for required or optional functionality. That won't be detected with this method.

当然,应用程序可以使用 LoadLibrary 系列函数来实现必需或可选的功能。这种方法不会检测到。

回答by Stephen Kellett

How about a DLL that you can call to calculate all this information for you and pass back the answer as an array of CStrings?

您可以调用一个 DLL 来为您计算所有这些信息并将答案作为 CString 数组传回?

PE Format DLLcan do this for you. Supplied with source code, no GPL restrictions. PE File Explorer is a GUI app that uses the DLL, also supplied with source (no GPL).

PE 格式 DLL可以为您做到这一点。提供源代码,没有 GPL 限制。PE 文件资源管理器是一个使用 DLL 的 GUI 应用程序,也提供源代码(无 GPL)。