und hallo! :D
ich habe ewig nach infos zum pe format gesucht aber nur sehr mühsam und nach langer zeit gefunden was ich brauchte!
genau aus dem grund schreibe ich hier meine erfahrungen zum thema PE, es soll kein tutorial werden, nur eine kleine übersicht!
ich werde auch kleine c++ codesnippets mit einfügen!
okey wie fang ich an... ich denke erstmal mit einer kleinen liste was ich alles schreibe:
- der dos header
- der nt header
- die sections
(hm das is weniger als ich gedacht habe :D)
- DER DOS HEADER -
dann starte ich mal!
hier gehts um den DOS header (auch bekannt als MZ header):
ich beschreibe hier die (für mich) relevanten einträge..
der wichtigste eintrag ist e_magic!
e_magic enthält 2 bytes (WORD) die bei einer ausführbaren datei 'MZ' sein müssen, sonst bricht der windoof-pe-loader die ausführung ab.
wie man dadraus erkennen kann: die signatur!
der 2. wichtige eintrag ist e_lfanew, e_lfanew enthält das offset zum eigentlich wichtigen header! (absolutes file offset)
das wars (aus meiner sicht) schon mit dem DOS header :>
- DER NT HEADER -
... besteht aus 2. headern und der PE signatur.
in der IMAGE_NT_HEADERS struktur wird der Signatur wert auf 'PE' geprüft. wenn der nicht PE enthält -> abbrechen! (wie beim MZ)
was die anderen strukturen angeht sollten die einträge auch selbsterklärend sein! (bis hier kann man alles schnell nachgooglen!)
wirklich wichtig waren mir ImageBase und SizeOfImage!
bei ImageBase handelt es sich um die adresse, an die alles gemappt werden soll!
wenn man also code hat der an offset 0x1F steht (hier als beispiel einfach mal:
) und ImageBase=0x00401000 ist (was dem standard entspricht), liegt der code an ImageBase+offset=0x0040101F! (dazu später mehr)
bei SizeOfImage handelt es sich ganz einfach um die summe der virtuellen grösse aller sections!
(auch das lässt sich bis hier noch alles nachgooglen!)
- DIE SECTIONS -
hier gehts schon in den schwierigeren bereich!
direkt nach dem nt header folgen die sections, ein array aus dem IMAGE_SECTION_HEADER mit der grösse von ntheader.FileHeader.NumberOfSections...
Name gibt hier (wie man sich wohl denken kann) den namen der section!
Misc ist zur ladezeit die virtuelle grösse der section und nach dem laden die eigentliche adresse zu der section!
VirtualAddress ist das offset, an das die section geladen werden soll (ImageBase+VirtualAddress=addresse)!
SizeOfRawData gibt die grösse der section in der datei an...
PointerToRawData gibt das offset zu der section in der datei an!
und das war jetzt die zusammenfassung was wozu gut ist (im bereich bearbeiten und nicht erstellen)
ich werde das hier evtl. noch ein wenig erweitern...
ich habe ewig nach infos zum pe format gesucht aber nur sehr mühsam und nach langer zeit gefunden was ich brauchte!
genau aus dem grund schreibe ich hier meine erfahrungen zum thema PE, es soll kein tutorial werden, nur eine kleine übersicht!
ich werde auch kleine c++ codesnippets mit einfügen!
okey wie fang ich an... ich denke erstmal mit einer kleinen liste was ich alles schreibe:
- der dos header
- der nt header
- die sections
(hm das is weniger als ich gedacht habe :D)
- DER DOS HEADER -
dann starte ich mal!
hier gehts um den DOS header (auch bekannt als MZ header):
Code:
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
der wichtigste eintrag ist e_magic!
e_magic enthält 2 bytes (WORD) die bei einer ausführbaren datei 'MZ' sein müssen, sonst bricht der windoof-pe-loader die ausführung ab.
wie man dadraus erkennen kann: die signatur!
der 2. wichtige eintrag ist e_lfanew, e_lfanew enthält das offset zum eigentlich wichtigen header! (absolutes file offset)
das wars (aus meiner sicht) schon mit dem DOS header :>
- DER NT HEADER -
... besteht aus 2. headern und der PE signatur.
Code:
typedef struct _IMAGE_NT_HEADERS
{
ULONG Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
Code:
typedef struct _IMAGE_FILE_HEADER
{
WORD Machine;
WORD NumberOfSections;
ULONG TimeDateStamp;
ULONG PointerToSymbolTable;
ULONG NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Code:
typedef struct _IMAGE_OPTIONAL_HEADER
{
WORD Magic;
UCHAR MajorLinkerVersion;
UCHAR MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint;
ULONG BaseOfCode;
ULONG BaseOfData;
ULONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
ULONG SizeOfHeapReserve;
ULONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
was die anderen strukturen angeht sollten die einträge auch selbsterklärend sein! (bis hier kann man alles schnell nachgooglen!)
wirklich wichtig waren mir ImageBase und SizeOfImage!
bei ImageBase handelt es sich um die adresse, an die alles gemappt werden soll!
wenn man also code hat der an offset 0x1F steht (hier als beispiel einfach mal:
Code:
var1=var2;
bei SizeOfImage handelt es sich ganz einfach um die summe der virtuellen grösse aller sections!
(auch das lässt sich bis hier noch alles nachgooglen!)
- DIE SECTIONS -
hier gehts schon in den schwierigeren bereich!
direkt nach dem nt header folgen die sections, ein array aus dem IMAGE_SECTION_HEADER mit der grösse von ntheader.FileHeader.NumberOfSections...
Code:
typedef struct _IMAGE_SECTION_HEADER
{
UCHAR Name[8];
ULONG Misc;
ULONG VirtualAddress;
ULONG SizeOfRawData;
ULONG PointerToRawData;
ULONG PointerToRelocations;
ULONG PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
ULONG Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
Misc ist zur ladezeit die virtuelle grösse der section und nach dem laden die eigentliche adresse zu der section!
VirtualAddress ist das offset, an das die section geladen werden soll (ImageBase+VirtualAddress=addresse)!
SizeOfRawData gibt die grösse der section in der datei an...
PointerToRawData gibt das offset zu der section in der datei an!
und das war jetzt die zusammenfassung was wozu gut ist (im bereich bearbeiten und nicht erstellen)
ich werde das hier evtl. noch ein wenig erweitern...