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