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);
      
}


        
      
anhtuaninfoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.