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

如何使用c++和Windows解析EXE文件并从IMAGE\u DOS\u头结构中获取数据。h?

  •  5
  • Dsdsd  · 技术社区  · 7 年前

    我试图在windows中解析PE文件,并从该结构中获取数据

    IMAGE_DOS_HEADER

     #include <Windows.h>
        
        int main()
        {
            // open the file for binary reading
            std::ifstream file;
                file.open("D:/SomeProgram.exe", ios_base::binary);
        
            if (!file.is_open())
                return 1;
        
            // get the length of the file
            file.seekg(0, ios::end);
            size_t fileSize = file.tellg();
            file.seekg(0, ios::beg);
        
            // create a vector to hold all the bytes in the file
            std::vector<byte> data(fileSize, 0);
        
            // read the file
            file.read(reinterpret_cast<char*>(&data[0]), fileSize);
    

    我不知道如何获取包含 e_magic e_cbip , e_cp .... 最重要的是 e_ifanew 我知道,这个结构IMAGE\u DOS\u头存储在Windows中。h、 但我不知道如何使用它从任何exe文件中获取字段。

    3 回复  |  直到 4 年前
        1
  •  4
  •   Nishikant Mokashi    7 年前

    查找以下进程以从不同的标头获取数据:

    LPCSTR fileName; //exe file to parse
    HANDLE hFile; 
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
    PIMAGE_NT_HEADERS peHeader;
    
    hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    
    if(hFile==INVALID_HANDLE_VALUE)
    {
        printf("\n CreateFile failed in read mode \n");
        return 1;
    }
    
    hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
    
    if(hFileMapping==0)
    {
        printf("\n CreateFileMapping failed \n");
        CloseHandle(hFile);
        return 1;
    }
    
    lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);
    
    if(lpFileBase==0)
    {
        printf("\n MapViewOfFile failed \n");
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }
    
    dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;  //pointer to dos headers
    
    if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        //if it is executable file print different fileds of structure
        //dosHeader->e_lfanew : RVA for PE Header
        printf("\n DOS Signature (MZ) Matched");
    
        //pointer to PE/NT header
        peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
    
        if(peHeader->Signature==IMAGE_NT_SIGNATURE)
        {
            printf("\n PE Signature (PE) Matched \n");
            //important fileds
            //peHeader->FileHeader : Refrence to FileHeader
            //peHeader->OptionalHeader :  Refrence to Optional Header
            // lots of imprtant fileds are present in File header and Optional header to retrive code/data/different sections address of exe
    
        }
    
        UnmapViewOfFile(lpFileBase);
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 0;
    }
    else
    {
        printf("\n DOS Signature (MZ) Not Matched \n");
        UnmapViewOfFile(lpFileBase);
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }
    
        2
  •  3
  •   Jim Rhodes    7 年前

    声明结构实例并将数据复制到其中:

    IMAGE_DOS_HEADER idh;
    
    if ( fileSize >= sizeof(idh) )
    {
        std::memcpy(&idh, &data[0], sizeof(idh));
    }
    
        3
  •  1
  •   IXSO    6 年前

    将文件读入缓冲区并将其部分转换为结构。

    // READ FILE ASSUMING IT EXISTS AND IS A VALID PE FILE
    char* buffer = nullptr;
    std::ifstream infile("C:\\file.exe", std::ios::binary);
    
    std::filebuf* pbuf = infile.rdbuf();
    
    size_t size = pbuf->pubseekoff(0, infile.end, infile.in);
    
    buffer = new char[size];
    
    pbuf->pubseekpos(0, infile.in);
    pbuf->sgetn(buffer, size);
    
    infile.close();
    
    // CAST
    IMAGE_DOS_HEADER* MS_DOS = (IMAGE_DOS_HEADER*)buffer;
    IMAGE_NT_HEADERS* PE = (IMAGE_NT_HEADERS*)((DWORD)buffer + MS_DOS->e_lfanew);
    
    // DO YOUR STUFF
    // ...
    
    delete[] buffer;