PE
全文翻译摘抄自: https://0xrick.github.io/categories/#win-internals
PE (Portable Execute) 是可执行文件的一个总称,DLL,EXE等,专指32位可执行文件,64位的叫做PE+\PE32+,是一种扩展格式。
文件结构如下所示:
实在是复杂, 从上到下又分为 DOS头,NT头,节表以及具体的节,如下 .
- DOS 头, 64-bytes 长度 (又称MS-DOS Header)
- DOS Stub, 一段MS-DOS 2.0的兼容性执行程序,会打印”This program cannot be run in DOS mode” (当跑在DOS环境下时)
接下来是NT HEADER, 又分为好几个, 我们先用PE-bear打开一个exe瞧一眼
- PE signature, 4字节的签名表明这个文件时个PE文件
- PE 文件头, A standard COFF File Header(啥意思)
- 可选头, 是NT头中最重要的部分, 有些PE是没有这个的, 比如Object。exe是肯定有得, 能够给OS Loader提供很多信息.
接下来是SectionTable:
he section table follows the Optional Header immediately, it is an array of Image Section Headers, there’s a section header for every section in the PE file. Each header contains information about the section it refers to.
Section:
Sections are where the actual contents of the file are stored, these include things like data and resources that the program uses, and also the actual code of the program, there are several sections each one with its own purpose.
DOS HEADER
PE 文件中的前64字节, 在现代windows中已经不重要, 主要是”向后兼容(backward compatibility)”。
有了这64字节, PE就能够在DOS环境下执行(没试过,难以置信)。
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
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; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
对PE loader来说, 有些字段没那么重要。
- e_magic: It has a fixed value of 0x5A4D or MZ in ASCII, and it serves as a signature that marks the file as an MS-DOS executable
e_lfanew: it holds an offset to the start of the NT headers. 很重要, PE-Loader需要根据这个值去找 file header.
DOS Stub
是一段DOS程序, 打印” the executable is not compatible with DOS”然后退出。
NT Headers
分为64位和32位:
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
### Signatrue
4字节, 0x50450000, PE\0\0 in ASCII.
File Header
定义如下:
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
- Machine: 0x8864 for AMD64 and 0x14c for i386.
- NumberOfSections: 字面意思
- TimeDateStamp: 创建时间(unix时间戳)
- PointerToSymbolTable and NumberOfSymbols: 和符号表有关
- SizeOfOptionalHeader: 扩展头的长度
- Characteristics: 文件特征
Optional Header
非常重要的一个部分,分为32和64两个版本:
typedef struct _IMAGE_OPTIONAL_HEADER {
//..
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_OPTIONAL_HEADER64 {
// 略
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
- Magic: 0x10B (PE32), 0x20B(PE32+),0x107(ROM Image)
- SizeOfCode: .text段的长度
- SizeOfInitializedData: .data段的长度
- SizeOfUninitializedData: .bss段的长度
- AddressOfEntryPoint: 入口点,对dll来说是个可选项
- BaseOfData(PE32 Only): 第一个data section的地址
- Win32VersionValue: set to 0
- Subsystem: 控制台、应用程序之类详细请点击
导入表和导出表
导入表结构