Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 打印隐式链接的dll';可移植可执行文件中的.idata节中的_Windows_Executable_Exe_Portable Executable - Fatal编程技术网

Windows 打印隐式链接的dll';可移植可执行文件中的.idata节中的

Windows 打印隐式链接的dll';可移植可执行文件中的.idata节中的,windows,executable,exe,portable-executable,Windows,Executable,Exe,Portable Executable,我正在尝试编写一个代码,该代码应该通过使用exe的.idata部分中IMAGE\u IMPORT\u描述符结构的“name”字段打印出exe中所有导入dll的名称,但程序似乎陷入了无限循环。有人能告诉我如何把名字正确地打印出来吗 #include<iostream> #include<Windows.h> #include<stdio.h> #include<WinNT.h> int main()

我正在尝试编写一个代码,该代码应该通过使用exe的.idata部分中IMAGE\u IMPORT\u描述符结构的“name”字段打印出exe中所有导入dll的名称,但程序似乎陷入了无限循环。有人能告诉我如何把名字正确地打印出来吗

    #include<iostream>
    #include<Windows.h>
    #include<stdio.h>
    #include<WinNT.h>

    int main()
    {
        FILE *fp; 
        int i;

        if((fp = fopen("c:\\Linked List.exe","rb"))==NULL)
            std::cout<<"unable to open";


        IMAGE_DOS_HEADER imdh;
        fread(&imdh,sizeof(imdh),1,fp);
        fseek(fp,imdh.e_lfanew,0);

        IMAGE_NT_HEADERS imnth;
        fread(&imnth,sizeof(imnth),1,fp);

        IMAGE_SECTION_HEADER *pimsh;
        pimsh = (IMAGE_SECTION_HEADER *)malloc(sizeof(IMAGE_SECTION_HEADER) * imnth.FileHeader.NumberOfSections);

        long t;

        fread(pimsh,sizeof(IMAGE_SECTION_HEADER),imnth.FileHeader.NumberOfSections,fp);

        for(i=0;i<imnth.FileHeader.NumberOfSections;i++)
        {
            if(!strcmp((char *)pimsh->Name,".idata"))
                t = pimsh->PointerToRawData;
            pimsh++;
        }

        fseek(fp,t,0);

        IMAGE_IMPORT_DESCRIPTOR iid;
        char c;

        while(1)
        {
            fread(&iid,sizeof(iid),1,fp);

            if(iid.Characteristics == NULL)
                break;

            t = ftell(fp);

            fseek(fp,(long)iid.Name,0);

            while(c=fgetc(fp))
                printf("%c",c);
            printf("\n");

            fseek(fp,t,0);

        }
    }
#包括
#包括
#包括
#包括
int main()
{
文件*fp;
int i;
if((fp=fopen(“c:\\Linked List.exe”,“rb”))==NULL)

std::cout有几个问题

  • 您不能假定导入部分名为“.idata”。您应该使用
    IMAGE\u OPTIONAL\u头.DataDirectory[IMAGE\u DIRECTORY\u ENTRY\u import]
    定位导入

  • PE文件中的大多数偏移量是相对虚拟地址(RVA),而不是文件偏移量。要将RVA转换为偏移量,您需要确定虚拟地址所在的节,然后根据节在文件中的位置计算偏移量。具体来说,
    IMAGE\u IMPORT\u DESCRIPTOR.Name
    字段包含RVA,而不是文件偏移量

  • 如果使用内存映射文件而不是文件I/O,那么代码将更简单(更快)


解释RVA、数据目录等。它还包括
pedump
,一个具有转储PE文件的完整源代码的应用程序,这是一个有用的参考。

有几个问题

  • 您不能假定导入部分名为“.idata”。您应该使用
    IMAGE\u OPTIONAL\u头.DataDirectory[IMAGE\u DIRECTORY\u ENTRY\u import]
    定位导入

  • PE文件中的大多数偏移量是相对虚拟地址(RVA),而不是文件偏移量。要将RVA转换为偏移量,您需要确定虚拟地址所在的节,然后根据节在文件中的位置计算偏移量。具体来说,
    IMAGE\u IMPORT\u DESCRIPTOR.Name
    字段包含RVA,而不是文件偏移量

  • 如果使用内存映射文件而不是文件I/O,那么代码将更简单(更快)


解释RVA、数据目录等。它还包括
pedump
,一个具有转储PE文件完整源代码的应用程序,这是一个有用的参考。

mox的答案在所有方面都是正确的,但是我还想添加另一个解决方案-将文件作为图像加载以读取数据。
这只需使用一行代码即可实现

Base = LoadLibraryEx("c:\Linked List.exe", 0, DONT_RESOLVE_DLL_REFERENCES);
这会将可执行文件作为映像加载和映射,因此无需打开/读取/映射或将rva转换为原始偏移量

使用DONT_RESOLVE_DLL_REFERENCES标志,图像未初始化,因此所有导入数据都未被触及,入口点代码也不会执行。可执行文件只是映射到内存中

您只需使用Base+Rva查找导入的dll名称或任何其他类型的PE信息。

与FreeLibrary(Base)一起使用后释放可执行映像。

mox的答案在所有方面都是正确的,但是我还想添加另一个解决方案-将文件作为映像加载以读取数据。
这只需使用一行代码即可实现

Base = LoadLibraryEx("c:\Linked List.exe", 0, DONT_RESOLVE_DLL_REFERENCES);
这会将可执行文件作为映像加载和映射,因此无需打开/读取/映射或将rva转换为原始偏移量

使用DONT_RESOLVE_DLL_REFERENCES标志,图像未初始化,因此所有导入数据都未被触及,入口点代码也不会执行。可执行文件只是映射到内存中

您只需使用Base+Rva查找导入的dll名称或任何其他类型的PE信息。

在与FreeLibrary(Base)一起使用后释放可执行映像。

本文指出,“如果向下滚动到“PE文件导入”,则.idata部分(或导入表)以映像\导入\描述符数组开始。”节,第二段。@user1232138:那篇文章还指出Borland链接器不使用标准节名。关于节名:它们甚至不必有名称!同时开发我自己的PE分析工具(PeStudio)我曾经遇到过这样的情况:一些PE二进制文件的节名以不可打印字符开头,或者代码节名为“.idata”,等等。节名没有固定的规则!唯一的规则是:为它们的名称保留的位置由8个字节组成。本文说“The.idata节(或导入表)以图像\导入\描述符数组开始。“,如果向下滚动到“PE文件导入”部分,第二段。@user1232138:那篇文章还注意到Borland链接器不使用标准节名。关于节名:它们甚至不必有名称!在开发我自己的PE分析工具(PeStudio)时我曾经遇到过这样的情况:某些PE二进制文件的节名以不可打印字符开头,或者代码节名为“.idata”等。节名没有固定的规则!唯一的规则是:为其名称保留的位置由8个字节组成。根据:“…不要使用此值;它仅用于向后兼容。如果您计划仅访问DLL中的数据或资源,请使用LOAD_LIBRARY作为_DATAFILE_EXCLUSIVE或LOAD_LIBRARY作为_IMAGE_RESOURCE或两者。否则,请使用LoadLibrary函数将库作为DLL或可执行模块加载。“这要简单得多,但它将您限制为32位或64位DLL(取决于进程的风格)。@mox:是的,DONT_RESOLVE_DLL_引用适用于所有系统,因为它向后兼容,但直到Vista才支持LOAD_LIBRARY_as_DATAFILE_EXCLUSIVE和LOAD_LIBRARY_as_IMAGE_资源标志。根据:“…不要使用此值;它仅用于向后兼容。如果您计划仅访问DLL中的数据或资源,请使用LOAD_LIBRARY_AS_DATAFILE_EXCLUSI。”