PE小笔记(基础)
注:结构体可在vs的WINNT.H中查看
此处经供参考:(C:\Program Files\Microsoft Visual Studio\VC98\Include)
Dos头:
结构体:(共64字节)(4行)
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;
由于现在操作系统是32/64位,结构体中间数据无用,可修改且不影响程序运行
前个两字符:文件类型(作为标识,PE指纹) 例:4D 5A (MZ)可执行文件
最后的四个字节 : PE头位置(小端存储模式) 程序通过此寻找PE头位置
Dos块:位于Dos头于PE头中间 ,即如图所示部分编译器填充,可修改不影响程序运行 (如可添加病毒等)
PE头:
结构体:
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //PE标识
IMAGE_FILE_HEADER FileHeader; //标准PE头⭐
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //拓展PE头⭐
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
PE标识:(4字节)
不可破坏,系统运行时会检测此标识。
标准PE头:
结构体:(20字节)
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //可以运行在什么样的CPU上 (任意:0, intel 386及以后: 14C, x64 : 8664)
WORD NumberOfSections; //表示节的数量
DWORD TimeDateStamp; //编译器填写的时间戳,与文件属性中的(创建、修改时间)无关
DWORD PointerToSymbolTable; //调试相关
DWORD NumberOfSymbols; //调试相关
WORD SizeOfOptionalHeader; //可选PE头的大小(32位PE文件:0xE0 ,64位PE文件: 0xF0)
WORD Characteristics; //文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
举栗子:
对于这两行十六进制数:
64 86即(8664) —> 要求x64平台 ,12 00即(0012)表示共有12个节
81 35 72 5E即(5E723581)是一个秒的数字,自1970年00:00开始计算直到编译时截至过去的时间。(修改不影响程序运行)
F0 00即(0xF0)==>24字节
27 00即(0027)记录了文件属性,化为二进制后得:
0000 0000 0010 1110---------------对应下表得到文件属性信息
拓展PE头:
结构体(32位):
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic; //PE32:10B PE32+:20B
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; //内存中整个PE文件的映射尺寸,可比实际的值大,必须是SectionALign ment的整数倍
DWORD SizeOfHeaders; //所有头+节表按照文件对齐后的大小,否则加载会出错
DWORD CheckSum; //校验和,一些系统文件有要求用来判断文件是否被修改
WORD Subsystem; //子系统 驱动程序(1)图形界面(2)控制台、DLL(3)
WORD DllCharacteristics; //文件特性 不是针对DLL文件的
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;
结构体(64位):
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
ULONGLONG 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;
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;
程序真正执行的入口:内存镜像基质+程序入口
例如图中所示程序入口地址即为400000+01F8D0=41F8D0
文件对齐/内存对齐:记录不同状态下的对齐参数,例如上图中内存对齐参数为1000,文件对齐参数为0200.
内存映射尺寸(SizeOfImage):一定为内存对齐参数的整数倍,例:文件大小为3001,则内存中占用大小为4000。
SizeOfHeaders:一定为文件对齐参数整数倍
校验和:
计算方法:以两个字节为单位相加(溢出不用管)最终的结果+文件的长度=得到的值
可以人为修改且算法公开(毫无意义有木有)
文件特性如表所示:
节表
结构体(40字节):
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //ASCII字符串 可自定义 只截取8个
union { //Misc 双字 是该节在没有对齐前的真实尺寸,该值可以不准确
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress; //在内存中的偏移地址,价上ImageBase才是在内存中真正的地址
DWORD SizeOfRawData; //节在文件中对齐后的尺寸
DWORD PointerToRawData; //节区在文件中的偏移
DWORD PointerToRelocations; //调试相关
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; //节的属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
对于节属性可参照下表: