代码之家  ›  专栏  ›  技术社区  ›  ereOn

如何使用C++获取关于Windows可执行文件(.exe)的信息

  •  6
  • ereOn  · 技术社区  · 14 年前

    我必须创建一个软件,它将扫描几个目录并提取有关找到的可执行文件的信息。

    我需要做两件事:

    • 确定给定文件是否是可执行文件( .exe , .dll ,等等)-检查扩展可能不够好。
    • 获取有关此可执行文件的信息 公司名称 , the 产品名称 ,等等)。

    我以前从来没有这样做过,因此我不知道是否有一个Windows API(或轻量级C/C++库)来做这件事,或者它甚至是可能的。我想是的,因为 explorer.exe 做到了。

    你们知道什么能指引我正确的方向吗?

    非常感谢你的帮助。

    4 回复  |  直到 14 年前
        1
  •  9
  •   Jerry Coffin    14 年前

    你可以验证 PE File Format 随你所愿。如果你想,你也可以检查 PE file signature . 然后你可以使用 File Version API 检索公司名称、产品名称、版本号等。

        2
  •  7
  •   Vineel Kumar Reddy    14 年前

    请检查此代码并根据您的需要进行修改…

    http://pastebin.com/LYgVEd5u

    /*
    
    
                        Program to dump the PE,DOS headers and Hex Dump of particular section
                                                                            Sat 03/24/2007
                                                                                by
                                                                        K.Vineel Kumar Reddy
                                                                            In VC++ 6.0
    
    
                        ref : http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
                        tools used : Hiew
    
    
    
                      BRIEF VIEW OF PE FILE
    
                    .----------------------.
                    |                      |
                    |    Other stuff not   |
                    |    touched in this   |
                    |    program           |
                    |                      |
                    |----------------------|
                    |                      |
                    | Various Section like |
                    |        .....         |
                    |        .....         |
            .------>|       .reloc         |
            | .---->|       .idata         |
            | | .-->|       .data          |
            | | | .>|       .text          |
            | | | | |----------------------|
            '-|-|-|-|                      | <--- Each entry in section table have pointer
              '-|-|-|         Section      |      offsets to actual sections
                '-|-|     Header or Table  |
                  '-|                      |      ---.----------------.
                    |----------------------|-----/   |   PE Optional  |  1) ImageBase
                    |                      |         |    Header      |
                    |                      |         |                |
                    |        NT Headers    |         |----------------|
                    |                      |         |     COFF/PE    |  1) NumberOfSections
                    |                      |         |   Header Info  |  2) SizeOfOptionalHeader
                    |----------------------|-----    |----------------|
                    |         UNUSED       |     \   |   PE Signature |
                    |----------------------|      ---'----------------'
                    |      MS-DOS stub     |
                    |----------------------|
                    |         UNUSED       |
                    |----------------------|
                    |     MS-DOS Header    | <-- Here at 0x3c location we have the offset of NT Header
                    '----------------------'
    
    
    Structres related to these exe headers
    --------------------------------------
    1)   MS-DOS Header   ---> IMAGE_DOS_HEADER
    2)   NT Header       ---> IMAGE_NT_HEADERS --->contain 
                                               --->IMAGE_FILE_HEADER dealing with COFF/PE Header
                                               --->IMAGE_OPTIONAL_HEADER dealing with Optional PE Header
    
    3)   Section Table   ---> IMAGE_SECTION_HEADER
    
    Key Points 
    ----------
    
      dosHeader = Memory mapped base address
      ntHeader = (IMAGE_NT_HEADER)((DWORD)dosHeader + dosHeader->e_lfanew)
      sectionHeader = (IMAGE_SECTION_HEADER)((DWORD)ntHeader + OFFSET(OptionalHeader) + sizeof(OptionalHeader)) 
      each section = (char *)((DWORD)dosHeader + sectionHeader.PointerToRawData)
    
    
                                                                            ASCII ART by
                                                                             Vineel :)
    
    */
    
    
    
    
    
    
    
    
    
    #include<stdio.h> 
    #include<windows.h>
    #include<time.h>
    #include<tchar.h>
    
    void Help()
    {
        printf("\nUsage \ntest <path to exe file> [ -h <section> ]\n");
    }
    void HexDump(char * p ,int size,int secAddress)
    {
        int i=1,temp=0;
        wchar_t buf[18];      //Buffer  to store the character dump displayed at the right side 
        printf("\n\n%x: |",secAddress);
    
        buf[temp]    = ' ' ;  //initial space
        buf[temp+16] = ' ' ;  //final space 
        buf[temp+17] =  0  ;  //End of buf
        temp++;               //temp = 1;
        for( ; i <= size ; i++, p++,temp++)
        {
            buf[temp] = !iswcntrl((*p)&0xff)? (*p)&0xff :'.';
            printf("%-3.2x",(*p)&0xff );
    
            if(i%16 == 0){    //print the chracter dump to the right    
                _putws(buf);
                if(i+1<=size)printf("%x: ",secAddress+=16);
                temp=0;
            }
            if(i%4==0)printf("|");
        }
        if(i%16!=0){
            buf[temp]=0;
            for(;i%16!=0;i++)
                printf("%-3.2c",' ');
            _putws(buf);
        }
    }
    
    main(int argc , char ** argv){
    
        int i=0;
        HANDLE hMapObject,hFile;            //File Mapping Object
        LPVOID lpBase;                      //Pointer to the base memory of mapped file
        PIMAGE_DOS_HEADER dosHeader;        //Pointer to DOS Header
        PIMAGE_NT_HEADERS ntHeader;         //Pointer to NT Header
        IMAGE_FILE_HEADER header;           //Pointer to image file header of NT Header 
        IMAGE_OPTIONAL_HEADER opHeader;     //Optional Header of PE files present in NT Header structure
        PIMAGE_SECTION_HEADER pSecHeader;   //Section Header or Section Table Header
        if(argc>1){
    
            //Open the Exe File 
            hFile = CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            if(hFile == INVALID_HANDLE_VALUE){printf("\nERROR : Could not open the file specified\n"); goto info;};
    
            //Mapping Given EXE file to Memory
            hMapObject = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
            lpBase = MapViewOfFile(hMapObject,FILE_MAP_READ,0,0,0);
    
            //Get the DOS Header Base 
            dosHeader = (PIMAGE_DOS_HEADER)lpBase;// 0x04000000
    
            //Check for Valid DOS file
            if(dosHeader->e_magic == IMAGE_DOS_SIGNATURE){
                //Dump the Dos Header info
                printf("\nValid Dos Exe File\n------------------\n");
                printf("\nDumping DOS Header Info....\n---------------------------");
                printf("\n%-36s%s ","Magic number : ",dosHeader->e_magic==0x5a4d?"MZ(Mark Zbikowski)":"-");
                printf("\n%-36s%#x","Bytes on last page of file :",dosHeader->e_cblp);
                printf("\n%-36s%#x","Pages in file : ",dosHeader->e_cp);
                printf("\n%-36s%#x","Relocation : ",dosHeader->e_crlc);
                printf("\n%-36s%#x","Size of header in paragraphs : ",dosHeader->e_cparhdr);
                printf("\n%-36s%#x","Minimum extra paragraphs needed : ",dosHeader->e_minalloc);
                printf("\n%-36s%#x","Maximum extra paragraphs needed : ",dosHeader->e_maxalloc);
                printf("\n%-36s%#x","Initial (relative) SS value : ",dosHeader->e_ss);
                printf("\n%-36s%#x","Initial SP value : ",dosHeader->e_sp);
                printf("\n%-36s%#x","Checksum : ",dosHeader->e_csum);
                printf("\n%-36s%#x","Initial IP value : ",dosHeader->e_ip);
                printf("\n%-36s%#x","Initial (relative) CS value : ",dosHeader->e_cs);
                printf("\n%-36s%#x","File address of relocation table : ",dosHeader->e_lfarlc);
                printf("\n%-36s%#x","Overlay number : ",dosHeader->e_ovno);
                printf("\n%-36s%#x","OEM identifier : ",dosHeader->e_oemid);
                printf("\n%-36s%#x","OEM information(e_oemid specific) :",dosHeader->e_oeminfo);
                printf("\n%-36s%#x","RVA address of PE header : ",dosHeader->e_lfanew);
                printf("\n===============================================================================\n");
            }
            else {
                printf("\nGiven File is not a valid DOS file\n");
                goto end;
            }
    
            //Offset of NT Header is found at 0x3c location in DOS header specified by e_lfanew
            //Get the Base of NT Header(PE Header)  = dosHeader + RVA address of PE header
            ntHeader = (PIMAGE_NT_HEADERS)((DWORD)(dosHeader) + (dosHeader->e_lfanew));
            //Identify for valid PE file  
            if(ntHeader->Signature == IMAGE_NT_SIGNATURE){
                printf("\nValid PE file \n-------------\n");
    
                //Dump NT Header Info....
                printf("\nDumping COFF/PE Header Info....\n--------------------------------");
                printf("\n%-36s%s","Signature :","PE");
    
    
                //Get the IMAGE FILE HEADER Structure
                header = ntHeader->FileHeader;
    
                //Determine Machine Architechture
                printf("\n%-36s","Machine Architechture :");
                switch(header.Machine){ //Only few are determined (for remaining refer to the above specification)
                case 0x0:    printf("All "); break;
                case 0x14d:  printf("Intel i860"); break;
                case 0x14c:  printf("Intel i386,i486,i586"); break;
                case 0x200:  printf("Intel Itanium processor"); break;
                case 0x8664: printf("AMD x64"); break;
                case 0x162:  printf("MIPS R3000"); break;
                case 0x166:  printf("MIPS R4000"); break;
                case 0x183:  printf("DEC Alpha AXP"); break;
                default:     printf("Not Found"); break;
                }
                //Determine the characteristics of the given file
                printf("\n%-36s","Characteristics : ");
                if((header.Characteristics&0x0002) == 0x0002) printf("Executable Image ,");
                if((header.Characteristics&0x0020) == 0x0020) printf("Application can address > 2GB ,");
                if((header.Characteristics&0x1000) == 0x1000) printf("System file (Kernel Mode Driver(I think)) ,");
                if((header.Characteristics&0x2000) == 0x2000) printf("Dll file ,");
                if((header.Characteristics&0x4000) == 0x4000) printf("Application runs only in Uniprocessor ,");
    
    
                printf("\n%-36s%s","Time Stamp :",ctime(&(header.TimeDateStamp)));          //Determine Time Stamp
                printf("%-36s%d","No.sections(size) :",header.NumberOfSections);            //Determine number of sections
                printf("\n%-36s%d","No.entries in symbol table :",header.NumberOfSymbols);
                printf("\n%-36s%d","Size of optional header :",header.SizeOfOptionalHeader);
    
                printf("\n\nDumping PE Optional Header Info....\n-----------------------------------");
                //Info about Optional Header
                opHeader = ntHeader->OptionalHeader;
                //printf("\n\nInfo of optional Header\n-----------------------");
                printf("\n%-36s%#x","Address of Entry Point : ",opHeader.AddressOfEntryPoint);
                printf("\n%-36s%#x","Base Address of the Image : ",opHeader.ImageBase);
                printf("\n%-36s%s","SubSystem type : ",
                    opHeader.Subsystem==1?"Device Driver(Native windows Process)":
                opHeader.Subsystem==2?"Windows GUI":
                opHeader.Subsystem==3?"Windows CLI":
                opHeader.Subsystem==9?"Windows CE GUI":
                "Unknown"
                    );
                printf("\n%-36s%s","Given file is a : ",opHeader.Magic==0x20b?"PE32+(64)":"PE32");
                printf("\n%-36s%d","Size of code segment(.text) : ",opHeader.SizeOfCode);
                printf("\n%-36s%#x","Base address of code segment(RVA) :",opHeader.BaseOfCode);
                printf("\n%-36s%d","Size of Initialized data : ",opHeader.SizeOfInitializedData);
                printf("\n%-36s%#x","Base address of data segment(RVA) :",opHeader.BaseOfData);
                printf("\n%-36s%#x","Section Alignment :",opHeader.SectionAlignment);
                printf("\n%-36s%d","Major Linker Version : ",opHeader.MajorLinkerVersion);
                printf("\n%-36s%d","Minor Linker Version : ",opHeader.MinorLinkerVersion);              
    
    
    
                printf("\n\nDumping Sections Header Info....\n--------------------------------");
    
                //Retrive a pointer to First Section Header(or Section Table Entry)
    
    
                for(pSecHeader = IMAGE_FIRST_SECTION(ntHeader),i=0;i<ntHeader->FileHeader.NumberOfSections;i++,pSecHeader++){   
                    printf("\n\nSection Info (%d of %d)",i+1,ntHeader->FileHeader.NumberOfSections);
                    printf("\n---------------------");
                    printf("\n%-36s%s","Section Header name : ", pSecHeader->Name);
                    printf("\n%-36s%#x","ActualSize of code or data : ", pSecHeader->Misc.VirtualSize);
                    printf("\n%-36s%#x","Virtual Address(RVA) :", pSecHeader->VirtualAddress);
                    printf("\n%-36s%#x","Size of raw data (rounded to FA) : ", pSecHeader->SizeOfRawData);
                    printf("\n%-36s%#x","Pointer to Raw Data : ", pSecHeader->PointerToRawData);
                    printf("\n%-36s%#x","Pointer to Relocations : ", pSecHeader->PointerToRelocations);
                    printf("\n%-36s%#x","Pointer to Line numbers : ", pSecHeader->PointerToLinenumbers);
                    printf("\n%-36s%#x","Number of relocations : ", pSecHeader->NumberOfRelocations);
                    printf("\n%-36s%#x","Number of line numbers : ", pSecHeader->NumberOfLinenumbers);
                    printf("\n%-36s%s","Characteristics : ","Contains ");
                    if((pSecHeader->Characteristics&0x20)==0x20)printf("executable code, ");
                    if((pSecHeader->Characteristics&0x40)==0x40)printf("initialized data, ");
                    if((pSecHeader->Characteristics&0x80)==0x80)printf("uninitialized data, ");
                    if((pSecHeader->Characteristics&0x80)==0x80)printf("uninitialized data, ");
                    if((pSecHeader->Characteristics&0x200)==0x200)printf("comments and linker commands, ");
                    if((pSecHeader->Characteristics&0x10000000)==0x10000000)printf("shareable data(via DLLs), ");
                    if((pSecHeader->Characteristics&0x40000000)==0x40000000)printf("Readable, ");
                    if((pSecHeader->Characteristics&0x80000000)==0x80000000)printf("Writable, ");
    
    
                    // If -h or /h option is given then provide HexDump
                    if(argc==4&& (!strcmpi(argv[2],"-h")||!strcmpi(argv[2],"/h"))){
                        if(!strcmpi(argv[3],pSecHeader->Name))
                            if(pSecHeader->SizeOfRawData!=0)
                            HexDump((char *)((DWORD)dosHeader + pSecHeader->PointerToRawData) , pSecHeader->SizeOfRawData , opHeader.ImageBase + pSecHeader->VirtualAddress);
                    }
    
                }
    
    
                printf("\n===============================================================================\n");
            }
            else goto end;
    
    end:
            //UnMaping 
            UnmapViewOfFile(lpBase);
            CloseHandle(hMapObject);
        }
        else Help();
    info:
    
        printf("\
                \
                \
                                This Program is written by\
                                K.Vineel Kumar Reddy.\
                                        III/IV IT\
                                Gayathri Vidya Parishad college of Eng.\
                \
                \
                ");
    }
    
        3
  •  1
  •   Nick Meyer    14 年前

    你可能会发现 this CodeProject article which wraps the file version API 对第二项任务有帮助。若要检查文件是否可执行,可能需要分析 PE headers .

        4
  •  0
  •   ChrisW    14 年前

    并非所有可执行文件都是pe文件:例如,批处理/命令文件(在某种意义上)是可执行的,dos格式的可执行文件也是可执行的。