• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 744
  • Last Modified:

How to read PE header with "CArchive" or "fstream"


i want to read the PE header , here is my code, i see it ok, but i alway give the result is "0xeba1f0e" in my edit box for the   "ntHeader.Signature" while it must be "0x00004550"(PE00), though  i get the right result in "dosHeader.e_magic"=0x5a4d(MZ)


void CNewDlg::OnOpen()
{
         IMAGE_DOS_HEADER  dosHeader;
        IMAGE_NT_HEADERS  ntHeader;
        CString Display;
        UpdateData();

      char strFilter[] = { "EXE File(*.exe)|*exe|All Files (*.*)|*.*||" };
      CFileDialog dlgFile(TRUE, ".exe", NULL, 0, strFilter);

      if( dlgFile.DoModal() == IDOK )
      {
            ifstream stmHeader(dlgFile.GetFileName(), ios::binary);
          stmHeader.read((char *)&dosHeader, sizeof(dosHeader));
          stmHeader.read((char *)&ntHeader, sizeof(ntHeader));
       
            Display.Format("%x",ntHeader.Signature);
          m_headerInfo=Display;                  // m_headerInfo is a variable of an edit box that i use to display the result

      }
    UpdateData(FALSE);
      
}


        
      
0
anhtuaninfo
Asked:
anhtuaninfo
  • 2
  • 2
  • 2
2 Solutions
 
jkrCommented:
There seems to be a misconception about the header layout - see the code at http://support.microsoft.com/default.aspx?scid=kb;en-us;90493 ("HOWTO: How To Determine Whether an Application is Console or GUI"):

    /*
     *  Read the MS-DOS image header.
     */
    ReadBytes(hImage,
              &image_dos_header,
              sizeof(IMAGE_DOS_HEADER));

    if (IMAGE_DOS_SIGNATURE != image_dos_header.e_magic)
    {
        printf("Sorry, I do not understand this file.\n");
        exit(1);
    }

    /*
     *  Read more MS-DOS header.       */
    ReadBytes(hImage,
              MoreDosHeader,
              sizeof(MoreDosHeader));

    /*
     *  Get actual COFF header.
     */
    CoffHeaderOffset = AbsoluteSeek(hImage, image_dos_header.e_lfanew) +
                       sizeof(ULONG);

    ReadBytes (hImage, &ntSignature, sizeof(ULONG));

    if (IMAGE_NT_SIGNATURE != ntSignature)
    {
     printf("Missing NT signature. Unknown file type.\n");
     exit(1);
    }

    SectionOffset = CoffHeaderOffset + IMAGE_SIZEOF_FILE_HEADER +
                    IMAGE_SIZEOF_NT_OPTIONAL_HEADER;

    ReadBytes(hImage,
              &image_file_header,
              IMAGE_SIZEOF_FILE_HEADER);

    /*
     *  Read optional header.
     */
    ReadBytes(hImage,
              &image_optional_header,
              IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
0
 
anhtuaninfoAuthor Commented:

thank you very much,it's very useful for my shoolwork.

now ,i 've understanded why my code failed. it is simply because i don't know the exactly PE header which has some differrences from msdn:
        http://search.msdn.microsoft.com/search/results.aspx?qu=An+In-Depth+Look+into+the+Win32+Portable+Executable+File+Format&View=msdn&st=b&c=0&s=1&swc=0

The difference is "MoreDosHeader[16]".
But when i Insert the line :
     stmHeader.read((char*)MoreDosHeader,sizeof(MoreDosHeader));
after read dosHeader anh before read ntHeader, my code still dispaly the wrong result.
Do you know why???

0
 
jkrCommented:
I'd start with opening the file in a hex editor to check where the difference comes from.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
waysideCommented:
One of the members of the DOS header is a field called "e_lfanew", which contains the byte offset from the beginning of the file to where the PE header starts.

So after you read the dos header, you need to look in the structure for where the PE header really is, and seek that many bytes. Something like this:

    ifstream stmHeader(dlgFile.GetFileName(), ios::binary);
    stmHeader.read((char *)&dosHeader, sizeof(dosHeader));

    stmHeader.seekoff(dosHeader.e_lfanew, ios_base::beg);

    stmHeader.read((char *)&ntHeader, sizeof(ntHeader));
0
 
anhtuaninfoAuthor Commented:
i think we read the file on disk, so the parts of file follows the sequence order and needn't to seekoff, isn't it ???
0
 
waysideCommented:
There's a variable-sized chunk in there that holds the DOS stub program - this is the part that prints a message like "This program cannot be run in DOS mode" or "This program must be run under Win32" if you try and run it in DOS. Different linkers put different stubs in there, and leave different amounts of space before the NT header. The way you get around this variable-sized chunk is to look at the e_lfanew field in the dos header. This tells you the offset *from the beginning of the file* of where the NT header starts.

So you can figure out how many bytes to read by figuring out how many bytes you've already read and subtract that from e_lfanew and then read that many more to get to the NT header, or you can just jump there using seekoff(). There's nothing interesting in the DOS stub, so there's no reason to read it if you don't have to.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 2
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now