- Game Name
- N/A
- Anticheat
- N/A
- Coding Language
- N/A
After learning the basics of game hacking and reverse engineering you will have a very vague understanding of the PE File Format and the Windows Loader. After 6-12 months of learning you will want to take some time to get a better understanding of these things as they will be important for dealing with anticheat and antidebug.
Required Experience
Complete the Guide - START HERE Beginners Guide to Learning Game Hacking
Have a basic understanding of everything in Guide - Beginners Guide To Reverse Engineering Tutorial
Steps to Learn about PE Files and the Windows Loader
PE File Format & Header Resources
(the awesome image is from corkami)
The PE File Format is essentially defined by the PE Header so you will want to read about that first, you don't need to understand every single part of it but you should get an idea about it's structure and be able to identify the parts that are most important.
I will briefly talk about some of the important parts of the header, but refer you to the list of links below which will have a much better explanation. I will not go into depth here, view the resources for more specifics.
DOS Header
The first two bytes of the header are the magic bytes which identify the file type, 4D 5A or "MZ" which are the initials of Mark Zbikowski who worked on DOS at Microsoft. These magic bytes define it as a PE file. You will also find the string "This program cannot be run in DOS mode" which will appear if you try to run a Windows PE file in DOS. This is here for backwards compatibility.
At offset 0x60 of the DOS HEADER there is a variable named e_lfanew which contains the offset to the PE header
PE Header
This portion is small and simply contains a file signature which are the magic bytes 'PE\0\0' or 50 45 00 00.
COFF Header
COFF = Common Object File Format which is the format which predates the PE file format.
Optional Header
Now we're getting into the actual meat of the PE header. This is not actually optional, it's optional in context of COFF object files but not PE files. It contains many important variables such as AddressOfEntryPoint, ImageBase, Section Alignment, SizeOfImage, SizeOfHeaders and the DataDirectory. This structure has 32 bit and 64 bit versions.
Section Table
Contains an array of IMAGE_SECTION_HEADER structs which define the sections of the PE file such as the .txt and .data sections
After the section table comes the actual sections
Learn more specifics in the resources below
PE Resources
PE File Tools
pestudio is one of the best tools for examining PE files and the PE header for binaries, download it and checkout a view binaries with it.
PE-bear is also amazing, if you like it check out hasherezade's pe-sieve and her other repos she has some amazing stuff
PEExplorerV2 is my third favorite PE tool
We also have a collection of various PE related tools here Hacking Tools
Life of Binaries Video Series
This is a great playlist that will teach you alot about the PE file format and the Windows OS. You can also download the slides, graphics & more from their site LifeOfBinaries
Example of Parsing the PE Header
Parsing the Export Table
To give you an idea of what you can do by parsing the PE header here is a function from @iPower which shows you how to walk the export table and find the address of the exported function
C# Export Table Parsing
C# Get Address of Exported Function
Import Address Table Hooking
C++ IAT Hooking Source Code
Windows PE Loader
Here's some info from ARTeam's PE File Format Compendium which is an excellent resource for learning about this. This is the best little explanation of the PE Loader to get you started:
The Loader
When an executable is run, the windows loader creates a virtual address space for the process and maps the executable module from disk into the process' address space. It tries to load the image at the preferred base address and maps the sections in memory. The loader goes through the section table and maps each section at the address calculated by adding the RVA of the section to the base address. The page attributes are set according to the section’s characteristic requirements. After mapping the sections in memory, the loader performs base relocations if the load address is not equal to the preferred base address in ImageBase.
The import table is then checked and any required DLLs are mapped into the process' address space. After all of the DLL modules have been located and mapped in, the loader examines each DLL's export section and the IAT is fixed to point to the actual imported function address. If the symbol does not exist (which is very rare), the loader displays an error. Once all required modules have been loaded execution passes to the app's entry point
The area of particular interest in RCE is that of loading the DLLs and resolving imports. This process is complicated and is accomplished by various internal (forwarded) functions and routines residing in ntdll.dll which are not documented by Micro$oft. As we said previously function forwarding is a way for M$ to expose a common Win32 API set and hide low level functions which may differ in different versions of the OS. Many familiar kernel32 functions such as GetProcAddress are simply thin wrappers around ntdll.dll exports such as LdrGetProcAddress which do the real work
Learn how to Manual Map a DLL
Learning manual mapping is a great way to learn alot of it, but it's not for noobs. Make sure you have a solid understanding before diving into this. Manual mapping a DLL is essentially emulating everything LoadLibrary() does, by learning how to manual map you are learning how the Windows Loader loads a DLL.
The source code for the manual mapping routine in the GH Injector has been updated, you can download it here Guided Hacking DLL Injector
ReactOS
ReactOS can be regarded as a Windows clone, it can load PE files just like Windows so there source code is super helpful for learning about the internal workings of Windows. While we're talking about the Windows Loader, this function specifically is a great resource: CreateProcessInternal
Undocumented Windows API Functions & Structures
This isn't 100% on topic but I think it's something you will want to touch on at the same time you are learning about the things in this guide. You will need to access and use many undocumented Windows API functions and structures in the course of your hacking career. In the Windows SDK there is a file called winternl.h which has many structures which are important to us, but many of them have "Reserved" member variables that Microsoft doesn't want us to know about and doesn't want us to use so they are left undefined. Using the winternl.h versions will not allow you complete access to everything you may need.
One of the easiest things you can do to get experience dealing with Windows Internals is to play with some of these undocumented structures and functions. You can learn more about them in this tutorial
guidedhacking.com
Required Experience
Complete the Guide - START HERE Beginners Guide to Learning Game Hacking
Have a basic understanding of everything in Guide - Beginners Guide To Reverse Engineering Tutorial
Steps to Learn about PE Files and the Windows Loader
- Learn about PE File Format & PE Header using our collection of links
- Take a look at some binaries in PEStudio / pe-bear / PEExplorerV2
- Life of Binaries Youtube Playlist
- Try a few sample source codes which parse the PE header
- Learn how to Manual Map a DLL
- Checkout ReactOS's CreateProcessInternal function
PE File Format & Header Resources
(the awesome image is from corkami)
The PE File Format is essentially defined by the PE Header so you will want to read about that first, you don't need to understand every single part of it but you should get an idea about it's structure and be able to identify the parts that are most important.
I will briefly talk about some of the important parts of the header, but refer you to the list of links below which will have a much better explanation. I will not go into depth here, view the resources for more specifics.
DOS Header
The first two bytes of the header are the magic bytes which identify the file type, 4D 5A or "MZ" which are the initials of Mark Zbikowski who worked on DOS at Microsoft. These magic bytes define it as a PE file. You will also find the string "This program cannot be run in DOS mode" which will appear if you try to run a Windows PE file in DOS. This is here for backwards compatibility.
At offset 0x60 of the DOS HEADER there is a variable named e_lfanew which contains the offset to the PE header
C++:
struct DOS_Header
{
// short is 2 bytes, long is 4 bytes
char signature[2] = { 'M', 'Z' };
short lastsize;
short nblocks;
short nreloc;
short hdrsize;
short minalloc;
short maxalloc;
void *ss; // 2 byte value
void *sp; // 2 byte value
short checksum;
void *ip; // 2 byte value
void *cs; // 2 byte value
short relocpos;
short noverlay;
short reserved1[4];
short oem_id;
short oem_info;
short reserved2[10];
long e_lfanew; // Offset to the 'PE\0\0' signature relative to the beginning of the file
}
This portion is small and simply contains a file signature which are the magic bytes 'PE\0\0' or 50 45 00 00.
COFF Header
COFF = Common Object File Format which is the format which predates the PE file format.
C++:
struct COFFHeader
{
short Machine;
short NumberOfSections;
long TimeDateStamp;
long PointerToSymbolTable;
long NumberOfSymbols;
short SizeOfOptionalHeader;
short Characteristics;
}
Now we're getting into the actual meat of the PE header. This is not actually optional, it's optional in context of COFF object files but not PE files. It contains many important variables such as AddressOfEntryPoint, ImageBase, Section Alignment, SizeOfImage, SizeOfHeaders and the DataDirectory. This structure has 32 bit and 64 bit versions.
Section Table
Contains an array of IMAGE_SECTION_HEADER structs which define the sections of the PE file such as the .txt and .data sections
C++:
struct IMAGE_SECTION_HEADER
{
// short is 2 bytes
// long is 4 bytes
char Name[IMAGE_SIZEOF_SHORT_NAME]; // IMAGE_SIZEOF_SHORT_NAME is 8 bytes
union {
long PhysicalAddress;
long VirtualSize;
} Misc;
long VirtualAddress;
long SizeOfRawData;
long PointerToRawData;
long PointerToRelocations;
long PointerToLinenumbers;
short NumberOfRelocations;
short NumberOfLinenumbers;
long Characteristics;
}
Learn more specifics in the resources below
PE Resources
- PE Format - Win32 apps
- ARTeam's PE File Format Compendium
- Portable Executable File Format
- Andrey Bazhan | Windows Debugging and Troubleshooting
- PE-Portable-executable - aldeid
- x86 Disassembly/Windows Executable Files - Wikibooks, open books for an open world
- Inside Windows: Win32 Portable Executable File Format in Detail
- Inside Windows: An In-Depth Look into the Win32 Portable Executable File Format, Part 2
- PE
- http://www.darkblue.ch/programming/PE_Format.pdf
- Portable Executable - Wikipedia
- Learning binary file formats (work in progress)
PE File Tools
pestudio is one of the best tools for examining PE files and the PE header for binaries, download it and checkout a view binaries with it.
PE-bear is also amazing, if you like it check out hasherezade's pe-sieve and her other repos she has some amazing stuff
PEExplorerV2 is my third favorite PE tool
We also have a collection of various PE related tools here Hacking Tools
Life of Binaries Video Series
This is a great playlist that will teach you alot about the PE file format and the Windows OS. You can also download the slides, graphics & more from their site LifeOfBinaries
Example of Parsing the PE Header
Parsing the Export Table
To give you an idea of what you can do by parsing the PE header here is a function from @iPower which shows you how to walk the export table and find the address of the exported function
C++:
uintptr_t helpers::get_module_export( const char* module_name, const char* export_name )
{
if ( !module_name || !export_name )
return 0;
auto module_base = reinterpret_cast< uintptr_t >( GetModuleHandleA( module_name ) );
if ( !module_base )
return 0;
auto pimage_dos_header = reinterpret_cast< PIMAGE_DOS_HEADER >( module_base );
if ( pimage_dos_header->e_magic != IMAGE_DOS_SIGNATURE )
return 0;
auto pimage_nt_headers = reinterpret_cast< PIMAGE_NT_HEADERS >( module_base + pimage_dos_header->e_lfanew );
if ( pimage_nt_headers->Signature != IMAGE_NT_SIGNATURE )
return 0;
auto export_directory_rva = pimage_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if ( !export_directory_rva )
return 0;
auto pimage_export_directory = reinterpret_cast< PIMAGE_EXPORT_DIRECTORY >( module_base + export_directory_rva );
auto peat = reinterpret_cast< PDWORD >( module_base + pimage_export_directory->AddressOfFunctions );
auto pent = reinterpret_cast< PDWORD >( module_base + pimage_export_directory->AddressOfNames );
auto peot = reinterpret_cast< PWORD >( module_base + pimage_export_directory->AddressOfNameOrdinals );
unsigned short ordinal = 0;
for ( DWORD i = 0; i < pimage_export_directory->NumberOfNames; ++i )
{
if ( !lstrcmpiA( export_name, reinterpret_cast< const char* >( module_base + pent[i] ) ) )
{
ordinal = peot[i];
break;
}
}
return ordinal ? module_base + peat[ordinal] : 0;
}
C# Get Address of Exported Function
Import Address Table Hooking
C++ IAT Hooking Source Code
Windows PE Loader
Here's some info from ARTeam's PE File Format Compendium which is an excellent resource for learning about this. This is the best little explanation of the PE Loader to get you started:
The Loader
When an executable is run, the windows loader creates a virtual address space for the process and maps the executable module from disk into the process' address space. It tries to load the image at the preferred base address and maps the sections in memory. The loader goes through the section table and maps each section at the address calculated by adding the RVA of the section to the base address. The page attributes are set according to the section’s characteristic requirements. After mapping the sections in memory, the loader performs base relocations if the load address is not equal to the preferred base address in ImageBase.
The import table is then checked and any required DLLs are mapped into the process' address space. After all of the DLL modules have been located and mapped in, the loader examines each DLL's export section and the IAT is fixed to point to the actual imported function address. If the symbol does not exist (which is very rare), the loader displays an error. Once all required modules have been loaded execution passes to the app's entry point
The area of particular interest in RCE is that of loading the DLLs and resolving imports. This process is complicated and is accomplished by various internal (forwarded) functions and routines residing in ntdll.dll which are not documented by Micro$oft. As we said previously function forwarding is a way for M$ to expose a common Win32 API set and hide low level functions which may differ in different versions of the OS. Many familiar kernel32 functions such as GetProcAddress are simply thin wrappers around ntdll.dll exports such as LdrGetProcAddress which do the real work
Learn how to Manual Map a DLL
Learning manual mapping is a great way to learn alot of it, but it's not for noobs. Make sure you have a solid understanding before diving into this. Manual mapping a DLL is essentially emulating everything LoadLibrary() does, by learning how to manual map you are learning how the Windows Loader loads a DLL.
The source code for the manual mapping routine in the GH Injector has been updated, you can download it here Guided Hacking DLL Injector
ReactOS
ReactOS can be regarded as a Windows clone, it can load PE files just like Windows so there source code is super helpful for learning about the internal workings of Windows. While we're talking about the Windows Loader, this function specifically is a great resource: CreateProcessInternal
Undocumented Windows API Functions & Structures
This isn't 100% on topic but I think it's something you will want to touch on at the same time you are learning about the things in this guide. You will need to access and use many undocumented Windows API functions and structures in the course of your hacking career. In the Windows SDK there is a file called winternl.h which has many structures which are important to us, but many of them have "Reserved" member variables that Microsoft doesn't want us to know about and doesn't want us to use so they are left undefined. Using the winternl.h versions will not allow you complete access to everything you may need.
One of the easiest things you can do to get experience dealing with Windows Internals is to play with some of these undocumented structures and functions. You can learn more about them in this tutorial
Guide - Undocumented Windows Functions & Structures
Undocumented Windows API Functions & Structures You will need to access and use...
Last edited:




