首页
社区
课程
招聘
[原创]PE头、区段解析
发表于: 2021-11-30 11:12 24114

[原创]PE头、区段解析

2021-11-30 11:12
24114

感谢互联网的知识分享。

PE文件的全称是Portable Executable ,意为可移植的可执行文件,常见的有EXE,DLL,SYS,COM,OCX,PE文件是微软Windows操作系统上的程序文件。

简单来理解,就是一种数据结构。我们知道知道CPU只认识二进制数,所以可执行文件保存在磁盘中都是以二进制数保存的,不过为了查看,所以市面上的编辑器都是用16进制显示的,比如下面这样,使用010Editer打开一个PE文件:

image-20211129111842467

PE文件结构如下:

有的数据结构是用来执行的代码,有的数据结构是用来保存数据。

img

​ 首先是DOS头和DOS存根,它们的存在主要是用来兼容DOS系统。当我们的程序运行在DOS系统的时候,就会运行DOS存根中的代码,代码内容就是输出一段字符串告诉用户,这个程序不能在16位系统运行。

​ 而DOS头保存了程序的信息,DOS头的定义如下:

这里面有用的信息就两个:

image-20211130091959186

PE头结构如下:

image-20211130095442582

注意:e_magic是word类型,占两个字节;Signature是dword类型,占四个字节。

image-20211130094858189

image-20211130094838165

Signature表示是否是PE,vs中有一个宏来定义它:

image-20211130095739805

PE头其实由两部分组成,一个是标准PE文件头,一个是可选头。

先说标准PE头:

在VS中继续跟进查看PE文件头结构体:

下面做一些重点介绍:

Machine:

微软也给出了相应平台的宏定义:

image-20211130100226056

NumberOfSections:

用loadPE打开一个PE文件,可以看到其区段:

image-20211130100556885

常用区段:
.text: 代码段,里面的数据都是代码,有的编译器也叫做code段,其实都是宏定义的;
.data:数据段(可读写),存放全局变量和静态变量;
.rdata:数据段(只读);
.idata:导入数据区段,存放导入表数据信息;
.edata:导出数据区段,存放导出表数据信息;
.rsrc:资源段;
.bss:存放未初始化数据;
.crt:c++ 运行时库 runtime;
.reloc:重定位;
.tls:线程局部存储。

Characteristics

PE文件的属性,相应宏定义如下:

image-20211130102206861

其结构体成员如下:

Magic

宏定义PE是32位还是64位

AddressOfEntryPoint

Subsystem

可执行文件期望的子系统的值,宏定义如下:

image-20211130104831114

通过C++打印相关成员,在监视中,我们也能看到相关成员的属性值:

image-20211130110103689

区段也是一个结构:

image-20211130132800303

前面我们在loadPE中打开,已经能看到区段表相关信息:

image-20211130100556885

现在通过已经了解到的,模仿loadPE,用控制台程序写一个PE 区段表解析器。

Microsoft Visual Studio提供了一个宏(IMAGE_FIRST_SECTION )来定义定位区段表:

image-20211130135515691

以此来定义一个区段头:

然后去PE文件标准头的地址:

IMAGE_FILE_HEADER 有个值表示了区段数量,可以根据这个数量来进行遍历:

image-20211130133859342

代码如下:

image-20211130135847068

 
 
 
 
 
 
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;
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;
 
 
 
 
 
 
 
 
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;  //运行平台,在不同平台上,其值也不一样
    WORD    NumberOfSections; //区段数据数量
    DWORD   TimeDateStamp; //文件什么时候被创建的
    DWORD   PointerToSymbolTable; //指向符号表的偏移指针
    DWORD   NumberOfSymbols; //符号表中的符号数量
    WORD    SizeOfOptionalHeader; //文件头扩展头的大小
    WORD    Characteristics; //PE文件的属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;  //运行平台,在不同平台上,其值也不一样
    WORD    NumberOfSections; //区段数据数量
    DWORD   TimeDateStamp; //文件什么时候被创建的
    DWORD   PointerToSymbolTable; //指向符号表的偏移指针
    DWORD   NumberOfSymbols; //符号表中的符号数量
    WORD    SizeOfOptionalHeader; //文件头扩展头的大小
    WORD    Characteristics; //PE文件的属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
 
 
 
 
 
 
 
 
 
 
typedef struct _IMAGE_ROM_OPTIONAL_HEADER {
    WORD   Magic; //文件类型的标识 32位的PE还是64位PE
    BYTE   MajorLinkerVersion; //链接器主版本号
    BYTE   MinorLinkerVersion;//链接器子版本号
    DWORD  SizeOfCode; //区段的总大小
    DWORD  SizeOfInitializedData; //已初始化数据段的大小
    DWORD  SizeOfUninitializedData;//未初始化数据段的大小
    DWORD  AddressOfEntryPoint; // 程序入口RVA
    DWORD  BaseOfCode; //代码段机址RVA
    DWORD  BaseOfData;//数据段基址RVA
    DWORD  BaseOfBss;//入口点,文件在内存中的首选装入地址
    DWORD  GprMask;
    DWORD  CprMask[4];
    DWORD  GpValue;
} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER;
 
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;//映像文件在装入内存中区段的对齐大小 ,通常是0x1000
    DWORD       FileAlignment;//磁盘中节区对齐大小
    WORD        MajorOperatingSystemVersion;//操作系统最低版本的主版本号
    WORD        MinorOperatingSystemVersion;//操作系统最低版本的子版本号
    WORD        MajorImageVersion;
    WORD        MinorImageVersion;
    WORD        MajorSubsystemVersion;
    WORD        MinorSubsystemVersion;
    DWORD       Win32VersionValue; //保留值 最低为00000000
    DWORD       SizeOfImage;
    DWORD       SizeOfHeaders;//ms—dos头,pe头,区段表总和
    DWORD       CheckSum;//映像文件静态和
    WORD        Subsystem;//可执行文件期望的子系统的值
    WORD        DllCharacteristics;//dllMain函数何时被调用
    ULONGLONG   SizeOfStackReserve;//exe中线程被保存的堆栈大小
    ULONGLONG   SizeOfStackCommit;//栈初始化的内存大小 默认大小4kb
    ULONGLONG   SizeOfHeapReserve;//堆初始化的内存大小默认大小1mb
    ULONGLONG   SizeOfHeapCommit;//每次指派给堆的大小,默认4kb
    DWORD       LoaderFlags;// 和调试有关 模式0
    DWORD       NumberOfRvaAndSizes;//数据目录成员的数量 一般16
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_ROM_OPTIONAL_HEADER {
    WORD   Magic; //文件类型的标识 32位的PE还是64位PE
    BYTE   MajorLinkerVersion; //链接器主版本号
    BYTE   MinorLinkerVersion;//链接器子版本号
    DWORD  SizeOfCode; //区段的总大小
    DWORD  SizeOfInitializedData; //已初始化数据段的大小
    DWORD  SizeOfUninitializedData;//未初始化数据段的大小
    DWORD  AddressOfEntryPoint; // 程序入口RVA
    DWORD  BaseOfCode; //代码段机址RVA
    DWORD  BaseOfData;//数据段基址RVA
    DWORD  BaseOfBss;//入口点,文件在内存中的首选装入地址
    DWORD  GprMask;
    DWORD  CprMask[4];
    DWORD  GpValue;
} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER;
 
typedef struct _IMAGE_OPTIONAL_HEADER64 {
    WORD        Magic;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-11-30 14:02 被soloz编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (4)
雪    币: 5281
活跃值: (3944)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

楼主写的不错,帮你补充一下官方文档 PE Format


另外,老王卖瓜,自卖自夸。推荐你使用我的编辑器查看PE文件的结构。

(具体内容可参考我发的帖子 EDX编辑器, 下载地址 www.ed-x.cc )

还可以支持coff,elf, archive等。


2021-12-1 14:10
0
雪    币: 627
活跃值: (1568)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
谢谢师傅,学习了,我其实打算后面用mfc也自己写个解析器来着
2021-12-1 16:53
1
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
0ke
4
师兄好强
2022-1-16 11:58
0
雪    币: 689
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5


ollydbg x64也支持pe文件等文件结构解析.

2022-1-16 12:58
0
游客
登录 | 注册 方可回帖
返回
//