PE64(x64)
注意事项
64位PE文件被称为PE32+,PE+, PE64
解析x64位PE时应该注意地址大小,PE64涉及到指针时应该都是64位
PE64结构
IMAGE_DOS_HANDLE
PE64的DOS头与PE32没有区别
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;
IMAGE_NT_HEADERS64
PE64与PE32在扩展头上发生变化
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader; // 与PE32有区别
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
PE64的文件头与PE32没有区别
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; // 64位:0x8664 32位:0x014C
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; // 64位:0x00F0 32位:0x00E0
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
PE64的扩展头
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic; // 64位:0x20B 32位:0x10B
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
// 上半部分 与PE32一致
ULONGLONG ImageBase; // 不同 镜像基址是64位的数字
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
// 与PE32差距
ULONGLONG SizeOfStackReserve; //不同 初始栈大小 64位大小
ULONGLONG SizeOfStackCommit; //不同 栈增长大小 64位大小
ULONGLONG SizeOfHeapReserve; //不同 初始堆大小 64位大小
ULONGLONG SizeOfHeapCommit; //不同 堆增长大小 64位大小
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes; // 数据目录表还是16个
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
IMAGE_SECTION_HEADER
PE64的区段头与PE32没有区别
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
数据目录表
IMAGE_EXPORT_DIRECTORY(0 导出表)
这个结构体与PE32没有区别
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA 数组中每个元素4个字节的RVA
DWORD AddressOfNames; // RVA 数组中每个元素都是IMAGE_IMPORT_BY_NAME
DWORD AddressOfNameOrdinals; // RVA 数组中每个都是2个字节序号
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
IMAGE_IMPORT_DESCRIPTOR (1 导入表)
IMAGE_IMPORT_DESCRIPTOR 结构体与PE32没有区别
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} DUMMYUNIONNAME;
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
但是IAT 与INT指向的数组应该是 IMAGE_THUNK_DATA64
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;
IMAGE_RESOURCE_DIRECTORY (2 资源表)
资源表与PE32也是一样
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
// 资源目录项
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset:31;
DWORD NameIsString:1;
} DUMMYSTRUCTNAME;
DWORD Name;
WORD Id;
} DUMMYUNIONNAME;
union {
DWORD OffsetToData;
struct {
DWORD OffsetToDirectory:31;
DWORD DataIsDirectory:1;
} DUMMYSTRUCTNAME2;
} DUMMYUNIONNAME2;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
IMAGE_BASE_RELOCATION (5 重定位表)
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
// 重定位项
struct {
WORD Offset:12; // (1) 大小为12Bit的重定位偏移
WORD Type :4; // (2) 大小为4Bit的重定位信息类型值
//Type需要修复的值 32位:0x03 64位:0x10
}TypeOffset;
IMAGE_TLS_DIRECTORY64 (9 TLS表)
VA地址都是64位
typedef struct _IMAGE_TLS_DIRECTORY64 {
ULONGLONG StartAddressOfRawData; //x64位VA
ULONGLONG EndAddressOfRawData; //x64位VA
ULONGLONG AddressOfIndex; //x64位VA PDWORD
ULONGLONG AddressOfCallBacks; //x64位VA TLS回调地址 *;
DWORD SizeOfZeroFill;
union {
DWORD Characteristics;
struct {
DWORD Reserved0 : 20;
DWORD Alignment : 4;
DWORD Reserved1 : 8;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
} IMAGE_TLS_DIRECTORY64;
IMAGE_DELAYLOAD_DESCRIPTOR (13 延迟加载表)
没有区别
typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
union {
DWORD AllAttributes;
struct {
DWORD RvaBased : 1; // Delay load version 2
DWORD ReservedAttributes : 31;
} DUMMYSTRUCTNAME;
} Attributes;
DWORD DllNameRVA; // RVA to the name of the target library (NULL-terminate ASCII string)
DWORD ModuleHandleRVA; // RVA to the HMODULE caching location (PHMODULE)
DWORD ImportAddressTableRVA; // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
DWORD ImportNameTableRVA; // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
DWORD BoundImportAddressTableRVA; // RVA to an optional bound IAT
DWORD UnloadInformationTableRVA; // RVA to an optional unload info table
DWORD TimeDateStamp; // 0 if not bound,
// Otherwise, date/time of the target DLL
} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;
总结PE32与PE64区别
扩展头中基址大小是64位,初始栈和堆都是64位
导入表中导入地址表(IAT)和导入名称表(INT)指向的数组元素都是8个字节的函数地址(RVA)
TLS表中的VA地址都被换成64位
鉴于以上区别不能直接使用PE32的方式解析PE64。
64位PE
最新推荐文章于 2023-06-09 23:00:19 发布