www.xbdev.net
xbdev - software development
Sunday March 30, 2025
Home | Contact | Support

Chptr-2- Start of a PE.

Well the journey must start somewhere as they say....

To start with we must create a little application, a small Win32 exe that we can use to explore, as I mentioned earlier I was going to use notepad.exe, but I think its better if we start with our own code first.

The code and its output:

#include <windows.h>

 

#pragma comment(lib, "user32.lib")

 

int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)

{

int i = 0;

i++;

MessageBox(0, "Hello World", "Title Box", 0);

return 0;

};

 

 

So there you have it a simple piece of code - now if you compile it you'll get to files, "simple.obj(851 bytes)" and a "simple.exe(36,864 bytes)" (e.g. I called the file simple.cpp).

Note the differences in size, next what happens if we run our .exe in dos?

 

On with our exploration.... So now we have our PE file which we can play with, we've sort of got an idea of whats in there... a simple library call for a message box and an int i which is incremented once.

Lets dig out the PE header, see what it atucally lucks like a structure (its contained in winnt.h):

struct IMAGE_NT_HEADERS

{

DWORD                                                 Signature;

IMAGE_FILE_HEADER                     FileHeader;

IMAGE_OPTIONAL_HEADER32     OptionalHeader;

};

Well as you can see the PE Header is pretty simple... Let me just explain the sections.

Signature is a dword that contains the value "50h, 45h, 00h, 00h".  In human terms it contains the text "PE" followed by two null's.  This member is the PE signature so we can use it to verify that we have a PE on our hands.

FileHeader is another structure that contains information about the physical layout of the PE file such as the number of sections, the machine the file is targeted at (e.g. UNIX, Intel etc) .. and so on.

OptionalHeader is a structure that is in "all" PE's and contains information about the logical layout of the PE file.  Remember despite the word "Optional" in its name it is always there :)

 

Comment:

The signature may vary from PE to PE and can define other OS it was compiled for, e.g.:

4Dh 5Ah 00h 00h - Dos Signature

4Eh 45h 00h 00h - OS2 Signature

4Ch 45h 00h 00h - VxD Signature

50h 45h 00h 00h - WindowsNT Signature

So I know what your wondering now.... how do we even know where the PE Header begins.. because of this DOS Header and DOS Stub.  Well the DOS MZ Header is defined in winnt.h as well as:

struct IMAGE_DOS_HEADER // DOS .EXE header

{

WORD e_magic; // Magic number (e.g. 5A 4Dh)

WORD e_cblp; // Bytes on last page of file

WORD e_cp; // Pages in file

WORD e_crlc; // Relocations

WORD e_cparhdr; // Size of header in paragraphs

WORD e_minalloc; // Minimum extra paragraphs needed

WORD e_maxalloc; // Maximum extra paragraphs needed

WORD e_ss; // Initial (relative) SS value

WORD e_sp; // Initial SP value

WORD e_csum; // Checksum

WORD e_ip; // Initial IP value

WORD e_cs; // Initial (relative) CS value

WORD e_lfarlc; // File address of relocation table

WORD e_ovno; // Overlay number

WORD e_res[4]; // Reserved words ****2*4=8bytes***

WORD e_oemid; // OEM identifier (for e_oeminfo)

WORD e_oeminfo; // OEM information; e_oemid specific

WORD e_res2[10]; // Reserved words *** 10*2=20bytes**

LONG e_lfanew; // File address of new exe header (its an offset value from  the beginning of the file!!!!)

};

Okay I've listed the whole structure for IMAGE_DOS_HEADER above, but the only parts of it you'll really need to know is e_lfanew and e_magic.  The rest is just useless to us for the moment... and we can skip over it for now.

Let coding begin...

 

#include <windows.h>

#include <stdio.h>

// Output to a text file.

void output(char* str)

{

FILE *fp = fopen("output.txt", "a+");

fprintf(fp, "%s\n", str);

fclose(fp);

}

char buff[500];

// Entry point (its a windows entry point).

int _stdcall WinMain(HINSTANCE, HINSTANCE, char* k, int l)

{

// Open our file called simple.exe

FILE *pFile = fopen("simple.exe", "rb");

short unsigned int DOS_SIG;

fread(&DOS_SIG, 2, 1, pFile);

sprintf(buff, "DOS Signature at start of file: %x", DOS_SIG);

output(buff);

fclose(pFile);

}

And the output of this program would be to a text file called "output.txt" in the same directory... don't forget our PE that we compiled earlier has to be in the same directory as well.  The output in the output.txt file is:

DOS Signature at start of file: 5a4d

Wow, yup, its as I told you... we have the e_magic value of 5a4d in hex which is equal to IMAGE_DOS_SIGNATURE.  So next we have to get the e_lfanew value, which is a further 58 bytes along, so we'll read this value in now. (the 58 bytes  you can work out if you count the number of WORDs in the structure, remember 2 bytes per word, and remember to check for arrays).

 

#include <windows.h>

#include <stdio.h>

// Output to a text file.

void output(char* str)

{

FILE *fp = fopen("output.txt", "a+");

fprintf(fp, "%s\n", str);

fclose(fp);

}

char buff[500];

// Entry point (its a windows entry point).

int _stdcall WinMain(HINSTANCE, HINSTANCE, char* k, int l)

{

// Open our file called simple.exe

FILE *pFile = fopen("simple.exe", "rb");

short unsigned int DOS_SIG;

fread(&DOS_SIG, 2, 1, pFile);

sprintf(buff, "DOS Signature at start of file: %x", DOS_SIG);

output(buff);

// Skip the next 58 bytes.

fseek(pFile, 58, SEEK_CUR);

unsigned int e_lfanew;

fread(&e_lfanew, 2, 1, pFile);

sprintf(buff, "e_lfanew value is: %x", e_lfanew);

output(buff);

// Use the e_lfanew value to seek to the start of the PE Header

fseek(pFile, e_lfanew, SEEK_SET);

// See if we have a PE Header signature

short unsigned int NT_SIG;

fread(&NT_SIG, 2, 1, pFile);

sprintf(buff, "NT Signature at start of PE Header: %x", NT_SIG);

output(buff);

fclose(pFile);

}

And what does this wonderful program output?

DOS Signature at start of file: 5a4d
e_lfanew value is: e0
NT Signature at start of PE Header: 4550

Well there you go, I've got you to the start of the PE Header... we can see that the value 0x4550 is the value of an NT (windows) PE Header... its also defined as IMAGE_NT_SIGNATURE.

So what have we accomplished?  A lot, we've opened a PE and had a look in there, we've confirmed the DOS Signature and go tthe e_lfanew value and found out PE Header.  Remember though, the e_lfanew value is the offset relative to the beginning of the file.

 

 

 
Advert (Support Website)

 
 Visitor:
Copyright (c) 2002-2025 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.