快速查询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数据段(只读)
.crtc++ 运行时库 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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部