⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 list_imports.c

📁 全面揭示PE文件的核心机密!彻底揭开PE结构的面纱!
💻 C
字号:


    /* list_imports -- list imports of PE files in command line
     *
     * usage:
     *        list_imports [-d] [-q] file1 file2 ...
     *
     * sorry for the lot of casting - it's ugly but it helps :-)
     * (it's necessary because you have to calculate in byte offsets but C pointers
     * increment in pointed-to sizes, and you must change between RVAs and addresses)
     */


#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <getopts.h>


static debugmode;
    /* decide whether to dump debug-output */



    /* dump of import directory */
    /* section begins at pointer 'section base'
     * section RVA is 'section_rva'
     * import directory begins at pointer 'imp'
     * I left out all the bound/unbound stuff, and left out support for broken Borland linkers
     * (see 'pe_map.c' for complete version)
     */
static int dump_import_directory(const void *const section_base, const DWORD section_rva, const IMAGE_IMPORT_DESCRIPTOR * imp)
{
    /* get memory address given the RVA */
    #define adr(rva) ((const void*)((char*)section_base+((DWORD)(rva))-section_rva))

    /* continue until address inaccessible or there's no DLL name */
    for (; !IsBadReadPtr(imp, sizeof(*imp)) && imp->Name; imp++)
      {
          const IMAGE_THUNK_DATA *import_entry;

            /* output DLL's name */
          printf("\nfrom \"%s\":\n", (char *)adr(imp->Name));

          if(debugmode)
            printf("name table at %#lx, address table at %#lx\n",(unsigned long)imp->OriginalFirstThunk,(unsigned long)imp->FirstThunk);

          import_entry = adr(imp->OriginalFirstThunk);

            /* listing header */
          printf("%6s %s\n", "hint", "name");
          printf("%6s %s\n", "----", "----");

            /* loop to enumerate imported functions
             * ends when 0-bytes in name/ordinal found
             */
          for (; import_entry->u1.Ordinal; import_entry++)
            {
                    /* nameless import */
                if (IMAGE_SNAP_BY_ORDINAL(import_entry->u1.Ordinal))
                    printf("%6lu <ordinal>\n", IMAGE_ORDINAL(import_entry->u1.Ordinal));
                else
                  {     /* import with name */
                      const IMAGE_IMPORT_BY_NAME *name_import = adr(import_entry->u1.AddressOfData);
                        /* careful string output - some DLLs have horrible names */
                      printf("%6u %-20.50s\n", name_import->Hint, name_import->Name);
                  }
            }
      }


      /* was the loop ended because memory was not readable? */
    if (IsBadReadPtr(imp, sizeof(*imp)))
        {
            puts("!! import directory ended unexpectedly !!");
            return 1;
        }

    #undef adr

    return 0;
}


    /* load a file in RAM (memory-mapped)
     * return pointrer to loaded file
     * 0 if no success
     */
static void *get_mapped_file(const char *filename)
{
    HANDLE hFile, hMapping;
    void *basepointer;
    if ((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
      {
          if(debugmode) puts("(could not open)");
          return 0;
      }
    if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
      {
          if(debugmode) puts("(mapping failed)");
          CloseHandle(hFile);
          return 0;
      }
    if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
      {
          if(debugmode) puts("(view failed)");
          CloseHandle(hMapping);
          CloseHandle(hFile);
          return 0;
      }
    
    CloseHandle(hMapping);
    CloseHandle(hFile);

    return basepointer;
}


    /* this will return a pointer immediatly behind the DOS-header
     * 0 if error
     */
static void * skip_dos_stub(const IMAGE_DOS_HEADER * dos_ptr)
{
    /* look there's enough space for a DOS-header */
    if (IsBadReadPtr(dos_ptr, sizeof(*dos_ptr)))
        {
            puts("not enough space for DOS-header");
            return 0;
        }

     /* validate MZ */
     if (dos_ptr->e_magic != IMAGE_DOS_SIGNATURE)
        {
            puts("not a DOS-stub");
            return 0;
        }

    /* ok, then, go get it */
    return (char*)dos_ptr + dos_ptr->e_lfanew;
}


    /* find the directory's section index given the RVA
     * Returns -1 if impossible
     */
static int get_directory_index(const unsigned dir_rva, const unsigned dir_length, const int number_of_sections, const IMAGE_SECTION_HEADER *sections)
{
    int sect;
    int index = -1;
    
    for(sect=0;sect<number_of_sections;sect++)
    {
        /* output section data */
        if(debugmode)
            printf("section \"%.*s\": RVA %#lx, offset %#lx, length %#lx\n",
                    (int)IMAGE_SIZEOF_SHORT_NAME,
                    sections[sect].Name,
                    (unsigned long)sections[sect].PointerToRawData,
                    (unsigned long)sections[sect].VirtualAddress,
                    (unsigned long)sections[sect].SizeOfRawData
                   );

        /* compare directory RVA to section RVA */
        if(sections[sect].VirtualAddress<=dir_rva && dir_rva<sections[sect].VirtualAddress+sections[sect].SizeOfRawData)
            {
                if(debugmode)
                {
                    puts("  (taken this one)");
                    index = sect;
                }
                else
                    return sect;
            }
    }

    return index;
}


    /* dump imports of a single file
     * Returns 0 if successful, !=0 else
     * *** action starts here ***
     */
static int process_file(const char *filename)
{
    const void *basepointer;    /* Points to loaded PE file
                                 * This is memory mapped stuff
                                 */
    int number_of_sections;
    DWORD import_rva;           /* RVA of import directory */
    DWORD import_length;        /* length of import directory */
    int import_index;           /* index of section with import directory */

        /* ensure byte-alignment for struct tag_header
         * sorry, but it's necessary
         */
    #include <pshpack1.h>

    const struct tag_header
      {
          DWORD signature;
          IMAGE_FILE_HEADER file_head;
          IMAGE_OPTIONAL_HEADER opt_head;
          IMAGE_SECTION_HEADER section_header[];  /* this is an array of unknown length
                                                   * actual number in file_head.NumberOfSections
                                                   * if your compiler objects to it length 1 should work
                                                   */
      } *header;

      /* revert to regular alignment */
    #include <poppack.h>

      
    if (debugmode)
        printf("starting to process \"%s\"\n", filename);
    else
        puts(filename);

    /* first, load file */
    basepointer = get_mapped_file(filename);
    if (!basepointer)
        {
            puts("cannot load file");
            return 1;
        }

    /* get header pointer; validate a little bit */
    header = skip_dos_stub(basepointer);
    if (!header)
        {
            puts("cannot skip DOS stub");
            UnmapViewOfFile(basepointer);
            return 2;
        }

    /* look there's enough space for PE headers */
    if(IsBadReadPtr(header, sizeof(*header)))
        {
            puts("not enough space for PE headers");
            UnmapViewOfFile(basepointer);
            return 3;
        }

    /* validate PE signature */
    if(header->signature!=IMAGE_NT_SIGNATURE)
        {
            puts("not a PE file");
            UnmapViewOfFile(basepointer);
            return 4;
        }
    

    /* some debug output */
    if (debugmode)
        printf("file header at %#lx\n"
               "optional header at %#lx\n"
               "data directories at %#lx\n"
               "section headers at %#lx\n",
               (unsigned long)(long)((char*)header - (char*)basepointer + offsetof(struct tag_header,file_head)),
               (unsigned long)(long)((char*)header - (char*)basepointer + offsetof(struct tag_header,opt_head)),
               (unsigned long)(long)((char*)header - (char*)basepointer + offsetof(struct tag_header,opt_head) + offsetof(IMAGE_OPTIONAL_HEADER,DataDirectory)),
               (unsigned long)(long)((char*)header - (char*)basepointer + offsetof(struct tag_header,section_header))
              );

    /* get number of sections */
    number_of_sections = header->file_head.NumberOfSections;
    if(debugmode)
        printf("%d sections\n",number_of_sections);

    /* check there are sections... */
    if(number_of_sections<1)
        {
            puts("no sections???");
            UnmapViewOfFile(basepointer);
            return 5;
        }

    /* validate there's enough space for section headers */
    if(IsBadReadPtr(header->section_header, number_of_sections*sizeof(IMAGE_SECTION_HEADER)))
        {
            puts("not enough space for section headers");
            UnmapViewOfFile(basepointer);
            return 6;
        }

    /* get RVA and length of import directory */
    import_rva = header->opt_head.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    import_length = header->opt_head.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;

    if(debugmode)
            printf("import directory at offset %#lx, length %#lx\n",(unsigned long)import_rva,(unsigned long)import_length);

    /* check there's stuff to care about */
    if(!import_rva || !import_length)
        {
            puts("no imports");
            UnmapViewOfFile(basepointer);
            return 0;       /* success! */
        }

    /* get import directory pointer */
    import_index = get_directory_index(import_rva,import_length,number_of_sections,header->section_header);

    /* check directory was found */
    if(import_index <0)
        {
            puts("couldn't find import directory in sections");
            UnmapViewOfFile(basepointer);
            return 7;
        }

    /* ok, we've found the import directory... action! */
    {
        /* The pointer to the start of the import directory's section */
      const void * section_address = (char*)basepointer + header->section_header[import_index].PointerToRawData;
      if(dump_import_directory(section_address,
                               header->section_header[import_index].VirtualAddress,
                                        /* the last parameter is the pointer to the import directory:
                                         * section address + (import RVA - section RVA)
                                         * The difference is the offset of the import directory in the section
                                         */
                               (void*)((char*)section_address+import_rva-header->section_header[import_index].VirtualAddress)))
        {
            UnmapViewOfFile(basepointer);
            return 8;
        }
    }
    
    UnmapViewOfFile(basepointer);
    return 0;
}



int main(int argc, char **argv)
{
    /* handle command line switches and filenames */
    for (;;)
        switch (getopt(argc, argv, "dq"))
          {
              case 0:
                  if (process_file(optarg))
                    {
                        puts("no happy - aborting");
                        return EXIT_FAILURE;
                    }
                  else
                      break;
              case '?':
                  fputs("usage: list_imports {[-d|-q|-?|file}\n", stderr);
                  return EXIT_FAILURE;
              case 'd':
                  debugmode = 1;
                  break;
              case 'q':
                  debugmode = 0;
                  break;
              case EOF:
                  return EXIT_SUCCESS;  /* done */
          }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -