www.xbdev.net
xbdev - software development
Thursday October 31, 2024
Home | Contact | Support

Chptr-5- Sections Table

Well its taken us long enough to get here!  But finally we've nearly found our code that we compiled... so much checking and other things...   So stay with me just a little bit longer and you'll not be disappointed... as I must admit we haven't really discovered anything exciting yet!.. But we will by golly.. we will  !! :)

The sections table is just an array of structures... for example if we have 3 sections, we'll have 3 structures on after the other located here, which will tell us the size and offset to our section and what sort of information is in there.

 

struct IMAGE_SECTION_HEADER {

char Name[8];

union Misc

{

DWORD PhysicalAddress;

DWORD VirtualSize;

};

DWORD VirtualAddress;

DWORD SizeOfRawData;

DWORD PointerToRawData;

DWORD PointerToRelocations;

DWORD PointerToLinenumbers;

WORD NumberOfRelocations;

WORD NumberOfLinenumbers;

DWORD Characteristics;

};

So what are the structure members fore?  There meanings?  Well the only ones we need to understand are as follows:

Name - an 8 byte variable that represents the section name, e.g. its not a null terminated string.  And can have any name, even just a null.

VirtualAdress - The RVA of the section.  The PE loader examines and uses the value in this field when its mapping the sections into memory.  Thus if the value in this section is 1000h, and the PE file is loaded into memory at 400000h the section will be loaded at 401000h.

SizeOfRawData - The size of the sections data rounded up to the next multiple of "file" alignment.

PointerToRawData - The file offset of the beginning of the section.  The PE loader uses the value in this field to find where the data in the sections is in the file.

Characteristics - Contains flags which tell us whether the section contains exectuable code, initilisation data, if it can be written to or from etc.

 

One thing you should remember from previous tutorials is the member variable of IMAGE_FILE_HEADER, NumberOfSections.  This member variable tells us how many sections we have to read in.

So in we go...

#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; // Tells us how many sections are in the file.

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

// NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

struct stIMAGE_SECTION_HEADER

{

char Name[8];

DWORD skip1;

DWORD VirtualAddress;

DWORD SizeOfRawData;

DWORD PointerToRawData;

DWORD PointerToRelocations;

DWORD PointerToLinenumbers;

WORD NumberOfRelocations;

WORD NumberOfLinenumbers;

DWORD Characteristics;

};

stIMAGE_SECTION_HEADER Section;

// We get the nubmer of sections which we read in earlier.

unsigned int iNumSections = FileHeader.NumberOfSections;

for(unsigned int i=0; i<iNumSections; i++)

{

sprintf(buff, "\n----------Details for Section *%d* -------------", i+1);

output(buff);

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

sprintf(buff, "Section - Name %.8s", Section.Name);

output(buff);

sprintf(buff, "Section - VirtualAddress %x", Section.VirtualAddress);

output(buff);

sprintf(buff, "Section - SizeOfRawData %x", Section.SizeOfRawData);

output(buff);

sprintf(buff, "Section - PointerToRawData %x", Section.PointerToRawData);

output(buff);

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

output(buff);

}

fclose(pFile);

}

 

Well we have got a lot of code there now... man has that baby grown since chapter one! Shall we see what the output looks like (output.txt):

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

----------Details for Section *1* -------------
Section - Name .text
Section - VirtualAddress 1000
Section - SizeOfRawData 4000
Section - PointerToRawData 1000
Section - Characteristics 60000020

----------Details for Section *2* -------------
Section - Name .rdata
Section - VirtualAddress 5000
Section - SizeOfRawData 1000
Section - PointerToRawData 5000
Section - Characteristics 40000040

----------Details for Section *3* -------------
Section - Name .data
Section - VirtualAddress 6000
Section - SizeOfRawData 3000
Section - PointerToRawData 6000
Section - Characteristics c0000040

 

As you can see we read in the details for our 3 sections, and displayed the data for them... as you can see some of the data is pretty useless to us at the moment.. But I'll explain it in a sec to you.

Our offset to the sections table - OptionalHeader.SizeOfHeaders. ---- we set this to our VA (virtual address) so that we can use our RVA with respect to this value.

Lets take Section-1-'s details and examine them.

----------Details for Section *1* -------------
Section - Name .text - this tells us that the name of our section is .text, which is where our application starts
Section - VirtualAddress 1000 - this tells u the RVA of our section... used by the PE loader to load the section into memory.
Section - SizeOfRawData 4000 - size of the raw data in bytes, rounded up to the file alignment value (e.g. declared in OptinalHeaders as 1000h)
Section - PointerToRawData 1000 - the "file" offset to the beginning of the section
Section - Characteristics 60000020

 

 

 

 

 

 

 

 

 
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.