12

如何确定 DLL 的二进制文件取决于使用编程方法?

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

4

6 回答 6

10

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

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

我认为这应该为您提供所需的一切。

更新:

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

于 2009-02-28T01:43:05.047 回答
7

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

于 2009-02-28T01:19:19.253 回答
7

基于pedump代码的 76 行代码(不要忘记添加 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;
}
于 2010-11-22T17:35:50.977 回答
1

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

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

于 2009-02-28T01:46:52.870 回答
1

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

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

于 2012-05-08T18:24:38.887 回答
0

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

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

于 2010-04-09T10:38:04.750 回答