PE Structure -1
Article Directory
The object of this is to get to know the FIG.
1. Dos head
n Each PE file is a DOS program begins, with it, once the program is executed under DOS, DOS to recognize that this is a valid executable.
winnt.h
The DOS header structure:
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number, [4D 5A]==MZ
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
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // at 0x3c offset, File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
It always starts 4D 5A
.
The last e_lfanew
is important because it points to the PE file header.
A pe file into hexeditor, see 0x3c at the LONG
type of data that the PE Header starting offset, this offset imposed PE..(50 45 00 00)
at the beginning, marking the beginning of the PE file.
PE loader from the IMAGE_DOS_HEADER
structure of the e_lfanew
field to find PE Header
the starting offset, plus the base address pointer to get the PE header.
PNTHeader = ImageBase + dosHeader->e_lfanew
2. NT head
PE PE Header is associated structural NT image header IMAGE_NT_HEADER
abbreviation, the inside contains many important fields PE loader used.
winnt.h
NT structure in the head:
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature; //50 45 00 00 : P E . .
IMAGE_FILE_HEADER FileHeader; //+04h
IMAGE_OPTIONAL_HEADER64 OptionalHeader; //+18h
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //+04h
WORD NumberOfSections; //+06h store the number of struct IMAGE_SECTION_HEADER in section table
DWORD TimeDateStamp; //+08h
DWORD PointerToSymbolTable; //+0ch
DWORD NumberOfSymbols; //+10h,
WORD SizeOfOptionalHeader; //+14h,!!!!
WORD Characteristics; //+16h
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
The official document: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_file_header
The second field of said table block (section) is immediately after the NT header (recall PE paper).
The last field is the file properties.
IMAGE_OPTIONAL_HEADER64
IMAGE_FILE_HEADER
Not sufficient to define the properties of the PE files, but also IMAGE_OPTIONAL_HEADER64
the alternative configuration.
_IMAGE_FILE_HEADER
The SizeOfOptionalHeader
field stores its size, offset from the PE header 18h
plus the value of the field (to .text
), that IMAGE_OPTIONAL_HEADER64
portion.
Look at winnt.h
how to define this structure.
The official document: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_optional_header64
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint; //RVA address!!!!
DWORD BaseOfCode;
ULONGLONG ImageBase;
DWORD SectionAlignment; //内存中区块的对齐大小 0x1000==4kB
DWORD FileAlignment; //文件中区块的对齐大小 0x0200==512B
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem; //how to build the initial gui
WORD DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
General virus will change some individual fields.
ImageBase
Priority load address, exe always use a separate virtual address space in accordance with the address always charged, it does not require relocation information exe, dll address corresponding to the host may be occupied, so _IMAGE_FILE_HEADER
the IMAGE_FILE_RELOCS_STRIPPED
field, always exe 1, dll is always zero.
The last field is very important, the number of array elements 16, that is #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
, it is the data directory table .
This structure is used to define 16 individual sections of data blocks for many different purposes, such as export table, import table, and the resource relocation table.
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; //start RVA
DWORD Size; //length
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
// Directory Entries
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
3. Block Table
section table, also called the section table.
In execution when a PE file, windows are not particularly large at the outset of the entire file is read into memory, instead of using memory-mapped file with a similar mechanism.
windows loader establish the mapping between the virtual address and a good PE files only when loaded.
True if and only if executed to a memory page instruction or access data when a page, this page will only be submitted from disk into physical memory, this mechanism so that files that are loaded speed and file size not too great relationship.
Windows DOS loader loading portion, PE header portion and a section table (partition table) is not part of any special treatment, and attributes are automatically press section (block) at the time of the loading section (block) of processed differently.
Under normal circumstances, it will deal with the following aspects:
- Memory property page;
- Section offset address;
- The size of the section;
- Without festival map.
windows memory attribute is set in units of pages, so the sections to be aligned in memory units must be at least the size of one page, the system 32 is typically 4kB, 64-bit systems are generally 8Kb == 2000H.
Section start address in memory, and file respectively according _IMAGE_OPTIONAL_HEADER64
to SectionAlignment
and FileAlignment
aligned.
Section is actually a combination of the same attribute data. When the section is loaded into memory, with a corresponding memory section it has been given the same properties.
The size of the section is two-fold:
- The above mentioned alignment
- Leaving no space for initialized data section
Some sections need not memory-mapped, for example .reloc
, it is prepared for the loader.
PE file attributes of all sections are defined in the section table, the section table immediately PE header consists of a series _IMAGE_SECTION_HEADER
composed of a section to describe this structure, the order of arrangement is consistent with Section.
Section an empty table to _IMAGE_SECTION_HEADER
end, the number of the section in the table section structure is equal to the number plus one.
The official document: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_section_header
//winnt.h
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //size before assigned,usually used
} Misc;
DWORD VirtualAddress; //RVA actually,integral multiple of SectionAlignment
DWORD SizeOfRawData; //size after assigned by FileAlignment
DWORD PointerToRawData; // used in .obj file,point to the section in file.
//meaningless in exe
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; //rwx,by bit
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
#define IMAGE_SIZEOF_SECTION_HEADER 40
VirtualAddress、PointerToRawData
Very important.
Most blocks were accustomed to .
begin with, this is not necessary. With the name of the former $
block will be merged in accordance with dollars behind in alphabetical order at the time of loading.
Virus will open a new block
.text
The VirtualAddress
usually 0x1000.
4. Block
section, also called the Festival.
section | description |
---|---|
.text | It called the code under Borland c ++ compiler |
.data | You can read and write, store global or static variables |
Krdt | Read-only. Two cases: exe stored in the debug directory; storage instructions strings. |
.idata | Import table containing information dll will be merged into another block. |
.edata | Export table, exp file association, will be merged. |
.rsrc | Icons, menus, bitmaps, etc., can not be combined. |
.bss | Uninitialized data, has been replaced by extended .data |
.crt | c++ run time lib data |
.tls | thread local storage, it includes support for by __declspec(thread) data variables declared tls |
.reloc | Base address of the executable file relocation, generally only required dll. Exe linker does not give additional base relocation release mode. |
.sdata | By the global pointer relative addressing read and write data may be short |
.srdata | By global pointer relative addressing of short read-only data |
.pdata | Exception table containing the cpu based on IMAGE_RUNTIME_FUNCTION_ENTRY the type of array |
.debug$S | obj file format symbols codeview |
.debug$T | oobj file format type recording codeview |
.debug$P | Information (using precompiled header) header comprising precompiled |
.drectve | Only for the obj file, the connector comprising instructions, |
.didat | Import data in a non-release mode lazily- release mode these data are incorporated into other sections |
vc ++ code control with the following name: #pragma data_msg("NAME");
it tells the compiler is called the data into NAME
blocks, rather than the default .data block.
Block usually begins obj files are placed compiler. Obj linker and library block according to the attribute merged into a final block. One benefit is to save space.
Note that .rsrc,.reloc,.pdata
can not be merged into other blocks.
Align
After mapping, dos file header, PE header and the location and size of a block offset table are not changed.
By default, EXE
files in memory base address 0x00400000
, DLL
files are 0x10000000
.
When the file / memory, a block is less than 0x200 / 0x1000 bytes, the remaining space is filled with 00.
RVA conversion and file offset
RVA = VA - Image Base
File offset address relative to the beginning of the file byte offset 0; offset relative to the RVA is at 0x400000.
After calculating the RVA, RVA by subtracting the initial virtual offset section, add the final section of this file is the file offset offset address.
section | Starting virtual offset | Starting file offset |
---|---|---|
.text | 0x1000 | 0x0400 |
.data | 0xF000 | 0x0600 |
.rsrc | 0x018000 | 0x9400 |
Starting file offset view_IMAGE_SECTION_HEADER.PointerToRawData
RVA = virtual memory address (VA) - load the base address (Image Base)
File offset address = RVA - starting offset segment section start file offset +
For example, VA is known as 0x411210, the RVA = 0x011210, located in .data section, the FileOffset = 0x0600 + (0x011210 - 0xF000).