Printing out the names of implicitly linked dll's from .idata section in a portable executable

自古美人都是妖i 提交于 2019-12-20 03:52:36

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!