快速查询PE文件知识点和PE文件解析
PE(Portable Executable)
PE文件的全称是Portable Executable ,意为可移植的可执行文件,常见的有EXE,DLL,SYS,COM,OCX,PE文件是微软Windows操作系统上的程序文件

PE节
| 节名 | 说明 |
|---|---|
| .text | .text 节是供机器指令使用的默认节。一般情况下,在最终生成的可执行文件中,链接器将把每个.OBJ文件的.text节合并成一个巨大的、统一的.text节。 |
| .data | 全局和静态变量存储(在编译时初始化) |
| .bss | 全局和静态变量存储(在编译时不初始化) |
| .textbss | 启用增量链接 |
| .rsrc | .rsrc节用于储存模块资源,这些资源是可以嵌入到可执行文件中的二进制对象。例如,定制的鼠标光标、字体、程序图标、字符串表及版本信息都是标准的资源。资源还可以是应用程序需要的任意数据块(例如另一个可执行文件)。 |
| .idata | 存储有关导入库例程信息 |
| .edata | 存储有关导出库例程信息 |
| .reloc | 重定位 |
| .rdata | 数据段(只读) |
| .crt | c++ 运行时库 runtime |
| .tls | 线程局部存储 |
基础知识
-
基地址(ImageBase):当PE文件通过Windows加载器载入内存后,内存中的版本称为模块,映射文件的起始地址称为模块句柄,可通过模块句柄访问内存中其他数据结构,这个内存起始地址就称为基地址。
-
虚拟地址(VA,Virtual Address):在Windows系统中,PE文件被系统加载到内存后,每个程序都有自己的虚拟空间,这个虚拟空间的内存地址称为虚拟地址。
-
相对虚拟地址(RVA,Relative Virtual Address):可执行文件中,有许多地方需要指定内存中的地址。例如,应用全局变量时需要指定它的地址。为了避免在PE文件中出现绝对内存地址引入了相对虚拟地址,它就是在内存中相对于PE文件载入地址的偏移量。
它们之间的关系:虚拟地址(VA) = 基地址(Image Base)+相对虚拟地址(RVA)
-
文件偏移地址(Offset):当PE文件存储在磁盘中时,某个数据的位置相对于文件头的偏移量称为文件偏移地址(File Offset)。文件偏移地址从PE文件的第一个字节开始计数,起始值为0
PE 头解析
DOS头
DOS头和DOS存根,它们的存在主要是用来兼容DOS系统。当我们的程序运行在DOS系统的时候,就会运行DOS存根中的代码,代码内容就是输出一段字符串告诉用户,这个程序不能在16位系统运行。
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE headerWORD e_magic; // DOS头签名,4D5AWORD e_cblp; // 最后(部分)页中的字节数WORD e_cp; // 文件中的全部和部分页数WORD e_crlc; // 重定位表中的指针数WORD e_cparhdr; // 头部尺寸,以段落为单位WORD e_minalloc; // 所需的最小附加段WORD e_maxalloc; // 所需的最大附加段WORD e_ss; // 初始化的SS值(相对偏移量)WORD e_sp; // 初始化的SP值WORD e_csum; // 补码检验值WORD e_ip; // 初始化的IP值WORD e_cs; // 初始化的CS值(相对偏移量)WORD e_lfarlc; // 重定位表的字节偏移量WORD e_ovno; // 覆盖号WORD e_res[4]; // 保留字WORD e_oemid; // OEM 标识符(相对 e_oeminfo)WORD e_oeminfo; // OEM 信息; e_oemid specificWORD e_res2[10]; // 保留字LONG e_lfanew; // PE头的偏移位置} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
DOS存根
在DOS头下方,是个可选项,大小不固定,由代码与数据混合而成,一般从0x40开始
标识头
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_OS2_SIGNATURE 0x454E // NE
#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
#define IMAGE_VXD_SIGNATURE 0x454C // LE
#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
解析DOS头
#include
#include
using namespace std;void ImageDosHeader(_In_z_ const char* path)
{// 获取文件对象HANDLE hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);// 获取文件大小DWORD fSize = GetFileSize(hfile, NULL);char* pBuff = new char[fSize];DWORD dwReadSize = 0;// 读文件BOOL bSuccess = ReadFile(hfile, pBuff, fSize, &dwReadSize, NULL);if (bSuccess){PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;// DOS头签名cout << hex << pDosHeader->e_magic << endl;// PE头的偏移位置cout << hex << pDosHeader->e_lfanew << endl;}else (cout.write("打开文件失败", 20));CloseHandle(hfile);delete[] pBuff;
}void main()
{ImageDosHeader(R"(C:\Users\11981\Desktop\Project1\1.exe)");
}
NT头
typedef struct _IMAGE_NT_HEADERS64 {DWORD Signature; // 标识,0x00004550IMAGE_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;
NT头:文件头
typedef struct _IMAGE_FILE_HEADER {WORD Machine; // 运行平台WORD NumberOfSections; // 文件存在的区段数量DWORD TimeDateStamp; // PE文件的创建时间,一般有连接器填写DWORD PointerToSymbolTable; // COFF文件符号表在文件中的偏移DWORD NumberOfSymbols; // 符号表的数量WORD SizeOfOptionalHeader; // 可选PE头的大小WORD Characteristics; // 文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Machine:运行平台
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33 0x01d3
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FI
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
