问题
I am trying to write a code which is supposed to print out the names of all the imported dll's in the exe by using the 'name' field of the IMAGE_IMPORT_DESCRIPTOR structure in the .idata section of the exe, but the program seems to be getting stuck in an infinite loop. Can someone please tell me how to get the names printed out correctly...
#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);
}
}
回答1:
There are several problems.
You can't assume the import section is called ".idata". You should locate the imports using
IMAGE_OPTIONAL_HEADER.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
.Most offsets within a PE file are Relative Virtual Addresses (RVAs), not file offsets. To convert an RVA to an offset you need to determine which section the virtual address is in, then calculate an offset based on where the section is in the file. Specifically, the
IMAGE_IMPORT_DESCRIPTOR.Name
field contains an RVA, not a file offset.Your code will be much simpler (and quicker) if you use a memory-mapped file rather than file I/O.
This MSDN article explains RVAs, the data directory, etc. It also includes pedump
, an application with full source code for dumping PE files, which is a useful reference.
回答2:
The answer by mox is right on all points, however I would also like to add another solution - load the file as an image to read the data.
This is achieved very simply using LoadLibraryEx with just one line of code.
Base = LoadLibraryEx("c:\Linked List.exe", 0, DONT_RESOLVE_DLL_REFERENCES);
This load and maps your executable as an image, so no need for opening/reading/mapping or converting rva to raw offsets.
With the DONT_RESOLVE_DLL_REFERENCES flag the image is uninitialized, so all import data is untouched, and entrypoint code is not executed. The executable is just mapped into memory.
You can simply use Base + Rva to find imported dll name - or any other kind of PE information.
Free the executable image after use with FreeLibrary(Base)
来源:https://stackoverflow.com/questions/9656147/printing-out-the-names-of-implicitly-linked-dlls-from-idata-section-in-a-porta