本帖最后由 appsion 于 2020-10-30 22:00 编辑
PE 文件解析
新手学习PE文件解析记录, 持续更新. 部分参考来源于网络, 无法逐一标注, 如果侵权,请及时联系. 如有错误请指正,误喷.
概念:
PE: Portable Executable, 可移植的可执行的文件, 常见的EXE、DLL、OCX、SYS、COM都是PE文件, PE文件是微软Windows操作系统上的程序文件.
COFF:
common object file format, 通用对象文件格式, 指可执行文件(映像)和对象文件 32 位编程的格式,该格式可跨平台移植
ImageBase:
映象基址, 项目加载到内存的起始地址.
VA:
Virtual Address, 虚拟地址, 项目加载到内存后的实际地址
RVA:
Relative Virtual Address, 相对虚拟地址, 在映射文件中, 项目加载到内存后从映象文件的基址偏移的地址.
更多请参考: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table
1.1 PE文件结构:
结构体: IMAGE_DOS_HEADER
说明: MS-DOS兼容的PE头
长度: 64字节
头文件: winnt.h
帮助文档: 无
参考文档: 来源于网络
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_DOS_HEADER // DOS .EXE header
{
WORD e_magic; // 1. 文件标识
WORD e_cblp; // 2. 文件最后页的字节数
WORD e_cp; // 3. 文件页数
WORD e_crlc; // 4. 重定义元素个数
WORD e_cparhdr; // 5. 头部尺寸,以段落为单位
WORD e_minalloc; // 6. 所需的最小附加段
WORD e_maxalloc; // 7. 所需的最大附加段
WORD e_ss; // 8. 初始的SS值(相对偏移量)
WORD e_sp; // 9. 初始的SP值
WORD e_csum; // 10. 校验和
WORD e_ip; // 11. 初始的IP值
WORD e_cs; // 12. 初始的CS值(相对偏移量)
WORD e_lfarlc; // 13. 重分配表文件地址
WORD e_ovno; // 14. 覆盖号
WORD e_res[4]; // 15. 保留字
WORD e_oemid; // 16. OEM标识符(相对e_oeminfo)
WORD e_oeminfo; // 17. OEM信息
WORD e_res2[10]; // 18. 保留字
LONG e_lfanew; // 19. PE标头格式偏移地址, IMAGE_NT_HEADERS 的地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
参数说明: 仅供参考, 详细说明请参考原文.
e_magic:
DOS映像, "MZ". #define IMAGE_DOS_SIGNATURE 0x5A4D
e_lfanew:
PE标头格式偏移地址, 指向 IMAGE_NT_HEADERS 结构
结构体: IMAGE_NT_HEADERS
说明: PE标头格式
头文件: winnt.h
帮助文档: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_nt_headers32
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_NT_HEADERS
{
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
参数说明: 仅供参考, 详细说明请参考原文.
Signature:
PE映像的4字节签名 “PE00”. IMAGE_NT_SIGNATURE 0x00004550 // PE00
FileHeader:
通用文件头, IMAGE_FILE_HEADER 结构
OptionalHeader: 可选文件头, IMAGE_OPTIONAL_HEADER 结构
结构体: IMAGE_SECTION_HEADER
说明: 映像节表格式
头文件: winnt.h
帮助文档: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header
[Asm] 纯文本查看 复制代码
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;
参数说明: 仅供参考, 详细说明请参考原文.
Name:
节表名称, 8字节字符串。不支持长度超过8个字符的节名称。
Misc.PhysicalAddress:
节表的虚拟大小
Misc.PhysicalAddress
文件地址
VirtualAddress:
节表的RVA
SizeOfRawData
节表的文件数据大小
PointerToRawData
节表Raw(磁盘文件)的偏移
PointerToRelocations
节表的重新定位偏移。
PointerToLinenumbers
节表的行号项偏移。
NumberOfRelocations
节表的重新定位数量
NumberOfLinenumbers
节表的行号项数量。
Characteristics
特征
Characteristics 成员如下:
| 0x00000000 | Reserved. | | 0x00000001 | Reserved. | | 0x00000002 | Reserved. | | 0x00000004 | Reserved. | IMAGE_SCN_TYPE_NO_PAD | 0x00000008 | The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. | | 0x00000010 | Reserved. | IMAGE_SCN_CNT_CODE | 0x00000020 | The section contains executable code. | IMAGE_SCN_CNT_INITIALIZED_DATA | 0x00000040 | The section contains initialized data. | IMAGE_SCN_CNT_UNINITIALIZED_DATA | 0x00000080 | The section contains uninitialized data. | IMAGE_SCN_LNK_OTHER | 0x00000100 | Reserved. | IMAGE_SCN_LNK_INFO | 0x00000200 | The section contains comments or other information. This is valid only for object files. | | 0x00000400 | Reserved. | IMAGE_SCN_LNK_REMOVE | 0x00000800 | The section will not become part of the image. This is valid only for object files. | IMAGE_SCN_LNK_COMDAT | 0x00001000 | The section contains COMDAT data. This is valid only for object files. | | 0x00002000 | Reserved. | IMAGE_SCN_NO_DEFER_SPEC_EXC | 0x00004000 | Reset speculative exceptions handling bits in the TLB entries for this section. | IMAGE_SCN_GPREL | 0x00008000 | The section contains data referenced through the global pointer. | | 0x00010000 | Reserved. | IMAGE_SCN_MEM_PURGEABLE | 0x00020000 | Reserved. | IMAGE_SCN_MEM_LOCKED | 0x00040000 | Reserved. | IMAGE_SCN_MEM_PRELOAD | 0x00080000 | Reserved. | IMAGE_SCN_ALIGN_1BYTES | 0x00100000 | Align data on a 1-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_2BYTES | 0x00200000 | Align data on a 2-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_4BYTES | 0x00300000 | Align data on a 4-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_8BYTES | 0x00400000 | Align data on a 8-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_16BYTES | 0x00500000 | Align data on a 16-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_32BYTES | 0x00600000 | Align data on a 32-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_64BYTES | 0x00700000 | Align data on a 64-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_128BYTES | 0x00800000 | Align data on a 128-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_256BYTES | 0x00900000 | Align data on a 256-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_512BYTES | 0x00A00000 | Align data on a 512-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_1024BYTES | 0x00B00000 | Align data on a 1024-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_2048BYTES | 0x00C00000 | Align data on a 2048-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_4096BYTES | 0x00D00000 | Align data on a 4096-byte boundary. This is valid only for object files. | IMAGE_SCN_ALIGN_8192BYTES | 0x00E00000 | Align data on a 8192-byte boundary. This is valid only for object files. | IMAGE_SCN_LNK_NRELOC_OVFL | 0x01000000 | The section contains extended relocations. The count of relocations for the section exceeds the 16 bits that is reserved for it in the section header. If the NumberOfRelocations field in the section header is 0xffff, the actual relocation count is stored in the VirtualAddress field of the first relocation. It is an error if IMAGE_SCN_LNK_NRELOC_OVFL is set and there are fewer than 0xffff relocations in the section. | IMAGE_SCN_MEM_DISCARDABLE | 0x02000000 | The section can be discarded as needed. | IMAGE_SCN_MEM_NOT_CACHED | 0x04000000 | The section cannot be cached. | IMAGE_SCN_MEM_NOT_PAGED | 0x08000000 | The section cannot be paged. | IMAGE_SCN_MEM_SHARED | 0x10000000 | The section can be shared in memory. | IMAGE_SCN_MEM_EXECUTE | 0x20000000 | The section can be executed as code. | IMAGE_SCN_MEM_READ | 0x40000000 | The section can be read. | IMAGE_SCN_MEM_WRITE | 0x80000000 | The section can be written to. |
结构体: IMAGE_FILE_HEADER
说明: 通用文件头格式.
头文件: winnt.h
帮助文档: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header
[Asm] 纯文本查看 复制代码 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
处理器类型
NumberOfSections
创建映像日期和时间
PointerToSymbolTable
符号表的偏移量
NumberOfSymbols
符号表中的符号数。
SizeOfOptionalHeader
可选映像头(IMAGE_OPTIONAL_HEADER)的长度
Characteristics
特征
Machine 成员如下:
IMAGE_FILE_MACHINE_UNKNOWN | 0x0 | The content of this field is assumed to be applicable to any machine type | IMAGE_FILE_MACHINE_AM33 | 0x1d3 | Matsushita AM33 | IMAGE_FILE_MACHINE_AMD64 | 0x8664 | x64 | IMAGE_FILE_MACHINE_ARM | 0x1c0 | ARM little endian | IMAGE_FILE_MACHINE_ARM64 | 0xaa64 | ARM64 little endian | IMAGE_FILE_MACHINE_ARMNT | 0x1c4 | ARM Thumb-2 little endian | IMAGE_FILE_MACHINE_EBC | 0xebc | EFI byte code | IMAGE_FILE_MACHINE_I386 | 0x14c | Intel 386 or later processors and compatible processors | IMAGE_FILE_MACHINE_IA64 | 0x200 | Intel Itanium processor family | IMAGE_FILE_MACHINE_M32R | 0x9041 | Mitsubishi M32R little endian | IMAGE_FILE_MACHINE_MIPS16 | 0x266 | MIPS16 | IMAGE_FILE_MACHINE_MIPSFPU | 0x366 | MIPS with FPU | IMAGE_FILE_MACHINE_MIPSFPU16 | 0x466 | MIPS16 with FPU | IMAGE_FILE_MACHINE_POWERPC | 0x1f0 | Power PC little endian | IMAGE_FILE_MACHINE_POWERPCFP | 0x1f1 | Power PC with floating point support | IMAGE_FILE_MACHINE_R4000 | 0x166 | MIPS little endian | IMAGE_FILE_MACHINE_RISCV32 | 0x5032 | RISC-V 32-bit address space | IMAGE_FILE_MACHINE_RISCV64 | 0x5064 | RISC-V 64-bit address space | IMAGE_FILE_MACHINE_RISCV128 | 0x5128 | RISC-V 128-bit address space | IMAGE_FILE_MACHINE_SH3 | 0x1a2 | Hitachi SH3 | IMAGE_FILE_MACHINE_SH3DSP | 0x1a3 | Hitachi SH3 DSP | IMAGE_FILE_MACHINE_SH4 | 0x1a6 | Hitachi SH4 | IMAGE_FILE_MACHINE_SH5 | 0x1a8 | Hitachi SH5 | IMAGE_FILE_MACHINE_THUMB | 0x1c2 | Thumb | IMAGE_FILE_MACHINE_WCEMIPSV2 | 0x169 | MIPS little-endian WCE v2 |
Characteristics 成员如下:
IMAGE_FILE_RELOCS_STRIPPED | 0x0001 | Image only, Windows CE, and Microsoft Windows NT and later. This indicates that the file does not contain base relocations and must therefore be loaded at its preferred base address. If the base address is not available, the loader reports an error. The default behavior of the linker is to strip base relocations from executable (EXE) files. | IMAGE_FILE_EXECUTABLE_IMAGE | 0x0002 | Image only. This indicates that the image file is valid and can be run. If this flag is not set, it indicates a linker error. | IMAGE_FILE_LINE_NUMS_STRIPPED | 0x0004 | COFF line numbers have been removed. This flag is deprecated and should be zero. | IMAGE_FILE_LOCAL_SYMS_STRIPPED | 0x0008 | COFF symbol table entries for local symbols have been removed. This flag is deprecated and should be zero. | IMAGE_FILE_AGGRESSIVE_WS_TRIM | 0x0010 | Obsolete. Aggressively trim working set. This flag is deprecated for Windows 2000 and later and must be zero. | IMAGE_FILE_LARGE_ADDRESS_ AWARE | 0x0020 | Application can handle > 2-GB addresses. | | 0x0040 | This flag is reserved for future use. | IMAGE_FILE_BYTES_REVERSED_LO | 0x0080 | Little endian: the least significant bit (LSB) precedes the most significant bit (MSB) in memory. This flag is deprecated and should be zero. | IMAGE_FILE_32BIT_MACHINE | 0x0100 | Machine is based on a 32-bit-word architecture. | IMAGE_FILE_DEBUG_STRIPPED | 0x0200 | Debugging information is removed from the image file. | IMAGE_FILE_REMOVABLE_RUN_ FROM_SWAP | 0x0400 | If the image is on removable media, fully load it and copy it to the swap file. | IMAGE_FILE_NET_RUN_FROM_SWAP | 0x0800 | If the image is on network media, fully load it and copy it to the swap file. | IMAGE_FILE_SYSTEM | 0x1000 | The image file is a system file, not a user program. | IMAGE_FILE_DLL | 0x2000 | The image file is a dynamic-link library (DLL). Such files are considered executable files for almost all purposes, although they cannot be directly run. | IMAGE_FILE_UP_SYSTEM_ONLY | 0x4000 | The file should be run only on a uniprocessor machine. | IMAGE_FILE_BYTES_REVERSED_HI | 0x8000 | Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero. |
结构体: IMAGE_OPTIONAL_HEADER
说明: 可选的映像头格式。
头文件: winnt.h
帮助文档: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32
[Asm] 纯文本查看 复制代码 typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
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;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
参数说明: 仅供参考, 详细说明请参考原文.
Magic
映像类型
MajorLinkerVersion
链接器的主要版本号。
MinorLinkerVersion
链接器的次要版本号。
SizeOfCode
代码段的大小.
SizeOfInitializedData
初始化数据段的大小.
SizeOfUninitializedData
未初始化数据段的大小.
AddressOfEntryPoint
入口点地址.
BaseOfCode
代码基址.
BaseOfData
数据基址.
ImageBase
映像基址.
SectionAlignment
内存对齐.
FileAlignment
文件对齐
MajorOperatingSystemVersion
主操作系统的主要版本号.
MinorOperatingSystemVersion
主操作系统的次要版本号.
MajorImageVersion
映像的主要版本号.
MinorImageVersion
映像的次要版本号.
MajorSubsystemVersion
子系统的主要版本号.
MinorSubsystemVersion
子系统的次要版本号.
Win32VersionValue
此成员为保留成员.
SizeOfImage
映像内存大小.
SizeOfHeaders
DOS头、PE头、区块表的总大小.
CheckSum
映像文件校验和.
Subsystem
运行此映像所需的子系统
DllCharacteristics
映像的DLL特性
SizeOfStackReserve
初始化时的栈大小.
SizeOfStackCommit
初始化时实际提交的栈大小。
SizeOfHeapReserve
初始化时保留的堆大小.
SizeOfHeapCommit
初始化时实际提交的堆大小.
LoaderFlags
此成员已过时。
NumberOfRvaAndSizes
数据目录表的数量.
DataDirectory
数据目录表
Magic成员如下:
IMAGE_NT_OPTIONAL_HDR32_MAGIC | 0x10b | The file is an executable image. | IMAGE_NT_OPTIONAL_HDR64_MAGIC | 0x20b | The file is an executable image. | IMAGE_ROM_OPTIONAL_HDR_MAGIC | 0x107 | The file is a ROM image. |
Subsystem成员如下:
MAGE_SUBSYSTEM_UNKNOWN | 0 | Unknown subsystem. | IMAGE_SUBSYSTEM_NATIVE | 1 | No subsystem required (device drivers and native system processes). | IMAGE_SUBSYSTEM_WINDOWS_GUI | 2 | Windows graphical user interface (GUI) subsystem. | IMAGE_SUBSYSTEM_WINDOWS_CUI | 3 | Windows character-mode user interface (CUI) subsystem. | IMAGE_SUBSYSTEM_OS2_CUI | 5 | OS/2 CUI subsystem. | IMAGE_SUBSYSTEM_POSIX_CUI | 7 | POSIX CUI subsystem. | IMAGE_SUBSYSTEM_WINDOWS_CE_GUI | 9 | Windows CE system. | IMAGE_SUBSYSTEM_EFI_APPLICATION | 10 | Extensible Firmware Interface (EFI) application. | IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER | 11 | EFI driver with boot services. | IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER | 12 | EFI driver with run-time services. | IMAGE_SUBSYSTEM_EFI_ROM | 13 | EFI ROM image. | IMAGE_SUBSYSTEM_XBOX | 14 | Xbox system. | IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION | 16 | Boot application. |
DllCharacteristics成员如下:
| 0x0001 | Reserved. | | 0x0002 | Reserved. | | 0x0004 | Reserved. | | 0x0008 | Reserved. | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | 0x0040 | The DLL can be relocated at load time. | IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY | 0x0080 | Code integrity checks are forced. If you set this flag and a section contains only uninitialized data, set the PointerToRawData member ofIMAGE_SECTION_HEADER for that section to zero; otherwise, the image will fail to load because the digital signature cannot be verified. | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | 0x0100 | The image is compatible with data execution prevention (DEP). | IMAGE_DLLCHARACTERISTICS_NO_ISOLATION | 0x0200 | The image is isolation aware, but should not be isolated. | IMAGE_DLLCHARACTERISTICS_NO_SEH | 0x0400 | The image does not use structured exception handling (SEH). No handlers can be called in this image. | IMAGE_DLLCHARACTERISTICS_NO_BIND | 0x0800 | Do not bind the image. | | 0x1000 | Reserved | IMAGE_DLLCHARACTERISTICS_WDM_DRIVER | 0x2000 | A WDM driver. | | 0x4000 | Reserved. |
DataDirectory成员如下:
MAGE_DIRECTORY_ENTRY_ARCHITECTURE | 7 | Architecture-specific data | IMAGE_DIRECTORY_ENTRY_BASERELOC | 5 | Base relocation table | IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT | 11 | Bound import directory | IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR | 14 | COM descriptor table | IMAGE_DIRECTORY_ENTRY_DEBUG | 6 | Debug directory | IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT | 13 | Delay import table | IMAGE_DIRECTORY_ENTRY_EXCEPTION | 3 | Exception directory | IMAGE_DIRECTORY_ENTRY_EXPORT | 0 | Export directory | IMAGE_DIRECTORY_ENTRY_GLOBALPTR | 8 | The relative virtual address of global pointer | IMAGE_DIRECTORY_ENTRY_IAT | 12 | Import address table | IMAGE_DIRECTORY_ENTRY_IMPORT | 1 | Import directory | IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG | 10 | Load configuration directory | IMAGE_DIRECTORY_ENTRY_RESOURCE | 2 | Resource directory | IMAGE_DIRECTORY_ENTRY_SECURITY | 4 | Security directory | IMAGE_DIRECTORY_ENTRY_TLS | 9 | Thread local storage directory |
1.2 PE文件关键结构图:
1.3 获取PE头信息
1. DOS头
文件地址 + 0
2. PE头
文件地址 + IMAGE_DOS_HEADER.e_lfanew
3. 节表头
文件地址 + IMAGE_DOS_HEADER.e_lfanew + sizeof(IMAGE_NT_HEADERS)
或使用宏 IMAGE_FIRST_SECTION
[Asm] 纯文本查看 复制代码
// 读取文件
CFile m_file;
CFileException m_fileEx;
m_file.Open(FilePathName, CFile::modeRead | CFile::typeBinary, &m_fileEx);
unsigned int FileLenght = (unsigned int)m_file.GetLength();
DataBuff = new char[FileLenght];
m_file.Read(DataBuff, FileLenght);
m_file.Close();
// DOS头
IMAGE_DOS_HEADER * DosHead = (IMAGE_DOS_HEADER *)(DataBuff + 0);
// NT头
IMAGE_NT_HEADERS * NTHead = (IMAGE_NT_HEADERS *)(DataBuff + DosHead->e_lfanew);
// 节表头
IMAGE_SECTION_HEADER *SectionHead = (IMAGE_SECTION_HEADER *)(DataBuff + DosHead->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|