www.xbdev.net
xbdev - software development
Tuesday September 17, 2024
Home | Contact | Support
>>

Chptr-4- Optional Header

Shall we jump right in.. .the Optional Header structure follows imediately after the FileHeader Structure as contains an enourmas amount of information.  I'll show you what it looks like:

 

struct IMAGE_OPTIONAL_HEADER

{

//

// Standard fields.

//

WORD Magic;

BYTE MajorLinkerVersion;

BYTE MinorLinkerVersion;

DWORD SizeOfCode;

DWORD SizeOfInitializedData;

DWORD SizeOfUninitializedData;

DWORD AddressOfEntryPoint;

DWORD BaseOfCode;

DWORD BaseOfData;

//

// NT additional fields.

//

DWORD ImageBase;

DWORD SectionAlignment;

DWORD FileAlignment;

WORD MajorOperatingSystemVersion;

WORD MinorOperatingSystemVersion;

WORD MajorImageVersion;

WORD MinorImageVersion;

WORD MajorSubsystemVersion;

WORD MinorSubsystemVersion;

DWORD Win32VersionValue;

DWORD SizeOfImage;

DWORD SizeOfHeaders;

DWORD CheckSum;

WORD Subsystem;

WORD DllCharacteristics;

DWORD SizeOfStackReserve;

DWORD SizeOfStackCommit;

DWORD SizeOfHeapReserve;

DWORD SizeOfHeapCommit;

DWORD LoaderFlags;

DWORD NumberOfRvaAndSizes;

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

};

So that you don't loose hope, and who wouldn't ... after seeing this for the first time people usually think of turning back... but the only important members of the structure to us are the ones I've made black, and I've sort of greyed out the others.

I know.. I know... whats so important about these few member variables... well I'll tell you in a sec.  But first I must clarify a few simple things.  "RVA"s???  Well a big thing in PE's is RVA, which stands for Relative Virtual Address... say it with me... "Relative Virtual Address".. its important you know what it means as well.  As you know in a physical file you can refer to things relative to the start of file, the DOS_MZ signature :)  Well when the file is loaded into memory instead of refairing to the start of the file we use the start address of where its located in memory instead of the start of file.

Let me give you an example, if the file was loaded into memory starting at virtual address (VA) space 400000h and the program needed to start execution at the virtual address 401000h, then we can say that the program starts execution at RVA 1000h.  An RVA is relative to the starting VA of the module (a.k.a the file without the dos stuff).

Member Field of Optional Header Structure Description
AddressOfEntryPoint Its the RVA of the first instruction that will be exectued when the PE loader is ready to run the PE file.
ImageBase The preferred load address of the PE, for example if the value in this field is 400000h, the PE loader will "try" to load it into the virtual address space starting at 400000h.  Remember I said try, so if the PE loader can't load it there it may put it at some other starting address.
SectionAlignment As like disks memory is split up into sections... chunks... pieces.. etc... and they have a pre-defined size... this field says how big the sections are with our code and data in.  For example, if this field is 4096 (or 1000h), each section must start at a multiple of 4096 bytes... so if the section in memory starts at 401000h and is 10 bytes big,.. well the next section must be at 420000h even if the address space between 41000h and 402000h will be mostly unused.
FileAlignment The alignment of the sections in the "file"!.... remember SectionAlignment is for memory, this is for the alignment in the file.  For example.. if the value in this field is 512 (200h), each section must start at multiples of 512 bytes.  If the first section is at file offset 200h and the size is 10 bytes, the next section must be at location at file offset 400h: the space between the file offsets 522 and 1024 is unused/undefined.

MajorSubsystemVersion

MinorSubsystemVersion

The Windows subsytem version - e.g. versions over 4.0 contain a 3D look for dialog boxes etc.
SizeOfImage The total size of the PE in memory.  Its teh sum of all headers and sections aligned to SectionAlignment.
SizeOfHeaders The size of all headers+ the section table (not the sections).  In short this value is equal to the file size minus the combined size of all sections in the file.  You could use this value as an offset to the start of the first section.
Subsystem Windows GUI (2) or Windows CUI (1)(console).
DataDirectory Array of IMAGE_DATA_DIRECTOR structures.  Contains the information for import functions (e.g. if we import fro many external dlls etc the info is in here).

 

Well here is the section of code which expands of previous coding and tells us so much more information :)))

#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, 4, 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

unsigned int NT_SIG;

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

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

output(buff);

struct stIMAGE_FILE_HEADER

{

WORD Machine;

WORD NumberOfSections;

DWORD TimeDateStamp;

DWORD PointerToSymbolTable;

DWORD NumberOfSymbols;

WORD SizeOfOptionalHeader;

WORD Characteristics;

};

stIMAGE_FILE_HEADER FileHeader;

// Well lets just read in the whole lot in one go in to our defined structure

fread(&FileHeader, sizeof(FileHeader), 1, pFile);

// Output what we have found.

sprintf(buff, "FileHeader - Machine value: %x", FileHeader.Machine);

output(buff);

sprintf(buff, "FileHeader - NumberOfSections: %x", FileHeader.NumberOfSections);

output(buff);

sprintf(buff, "FileHeader - NumberOfSymbols: %x", FileHeader.NumberOfSymbols);

output(buff);

sprintf(buff, "FileHeader - SizeOfOptionalHeader: %x", FileHeader.SizeOfOptionalHeader);

output(buff);

sprintf(buff, "FileHeader - Characteristics: %x", FileHeader.Characteristics);

output(buff);

 

struct stIMAGE_OPTIONAL_HEADER

{

BYTE skip1[16];

DWORD AddressOfEntryPoint;

BYTE skip2[8];

DWORD ImageBase;

DWORD SectionAlignment;

DWORD FileAlignment;

BYTE skip3[8];

WORD MajorSubsystemVersion;

WORD MinorSubsystemVersion;

DWORD skip4;

DWORD SizeOfImage;

DWORD SizeOfHeaders;

DWORD skip5;

WORD Subsystem;

BYTE skip6[26];

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

};

stIMAGE_OPTIONAL_HEADER OptionalHeader;

fread(&OptionalHeader, sizeof(OptionalHeader), 1, pFile);

// Output what we have found.

sprintf(buff, "OptionalHeader - AddressOfEntryPoint value: %x", OptionalHeader.AddressOfEntryPoint);

output(buff);

sprintf(buff, "OptionalHeader - ImageBase value: %x", OptionalHeader.ImageBase);

output(buff);

sprintf(buff, "OptionalHeader - SectionAlignment value: %x", OptionalHeader.SectionAlignment);

output(buff);

sprintf(buff, "OptionalHeader - FileAlignment value: %x", OptionalHeader.FileAlignment);

output(buff);

sprintf(buff, "OptionalHeader - MajorSubsystemVersion value: %x", OptionalHeader.MajorSubsystemVersion);

output(buff);

sprintf(buff, "OptionalHeader - MinorSubsystemVersion value: %x", OptionalHeader.MinorSubsystemVersion);

output(buff);

sprintf(buff, "OptionalHeader - SizeOfImage value: %x", OptionalHeader.SizeOfImage);

output(buff);

sprintf(buff, "OptionalHeader - SizeOfHeaders value: %x", OptionalHeader.SizeOfHeaders);

output(buff);

sprintf(buff, "OptionalHeader - Subsystem value: %x", OptionalHeader.Subsystem);

output(buff);

 

fclose(pFile);

}

 

And the output for our little program (output.txt) is:

DOS Signature at start of file: 5a4d
e_lfanew value is: e0
NT Signature at start of PE Header: 4550
FileHeader - Machine value: 14c
FileHeader - NumberOfSections: 3
FileHeader - NumberOfSymbols: 0
FileHeader - SizeOfOptionalHeader: e0
FileHeader - Characteristics: 10f
OptionalHeader - AddressOfEntryPoint value: 1030
OptionalHeader - ImageBase value: 400000
OptionalHeader - SectionAlignment value: 1000
OptionalHeader - FileAlignment value: 1000
OptionalHeader - MajorSubsystemVersion value: 4
OptionalHeader - MinorSubsystemVersion value: 0
OptionalHeader - SizeOfImage value: 9000
OptionalHeader - SizeOfHeaders value: 1000
OptionalHeader - Subsystem value: 2

 

 

 

 

 

 

 

 
Advert (Support Website)

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