PE文件格式解析学习笔记(3)---PE Header(IMAGE_NT_HEADERS部分)

NT Header(Ⅱ)

NT Header是主要包含三大部分内容PE标志(PE Signature),PE文件头(PE_HEADER),PE可选头(OPTION_PE_HEADER)

PE文件格式概览

图片转自:https://blog.csdn.net/evileagle/article/details/11693499

PE可选头

PE可选头作为NT头的最后一部分,也是定义字段最多,占据存储最多的一部分结构体定义的头部信息,在定义的结构体中一般分为两种32位PE可选头或者64位可选头
32位PE可选头,定义结构体为typedef struct _IMAGE_NT_HEADERS占据大小为224Byte,31个字段
64位PE可选头,定义结构体为typedef struct _IMAGE_NT_HEADERS64占据大小为240Byte

32位PE可选头

typedef struct _IMAGE_OPTIONAL_HEADER 
{
+0x00    WORD    Magic;         
+0x02   BYTE      MajorLinkerVersion;     
+0x03   BYTE      MinorLinkerVersion;     
+0x04   DWORD   SizeOfCode;     
+0x08    DWORD   SizeOfInitializedData;   
+0x0C    DWORD   SizeOfUninitializedData; 
+0x10    DWORD   AddressOfEntryPoint;    // 程序执行入口RVA
+0x14    DWORD   BaseOfCode;      // 代码的区块的起始RVA
+0x18    DWORD   BaseOfData;      // 数据的区块的起始RVA
+0x1C    DWORD   ImageBase;      // 程序的首选装载地址
+0x20   DWORD   SectionAlignment;     
+0x24   DWORD   FileAlignment;     
+0x28    WORD    MajorOperatingSystemVersion; 
+0x2A    WORD    MinorOperatingSystemVersion;  
+0x2C    WORD    MajorImageVersion;       
+0x2E    WORD    MinorImageVersion;      
+0x30    WORD    MajorSubsystemVersion; 
+0x32    WORD    MinorSubsystemVersion;  
+0x34    DWORD   Win32VersionValue;       
+0x38    DWORD   SizeOfImage;       
+0x3C    DWORD   SizeOfHeaders;      
+0x40    DWORD   CheckSum;       
+0x44    WORD    Subsystem;      
+0x46    WORD    DllCharacteristics;      
+0x48    DWORD   SizeOfStackReserve;      
+0x4C    DWORD   SizeOfStackCommit;       
+0x50    DWORD   SizeOfHeapReserve;        
+0x54    DWORD   SizeOfHeapCommit;        
+0x58    DWORD   LoaderFlags;       
+0x5C    DWORD   NumberOfRvaAndSizes;     
+0x60    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
PE-Option-Header定义重要关键字段[12个]详解(共计224Byte)
字段 含义 大小 成员位置
Magic 识别可执行程序32位或64位 2Byte 1
AddressOfEntryPoint 程序入口地址 4Byte 7
ImageBase 内存镜像基址 4Byte 10
SectionAlignment 内存对齐 4Byte 11
FileAlignment 文件对齐 4Byte 12
SizeOfImage 内存中整个PE文件,就是PE文件展开后大小,是内存对齐整数倍 2Byte 20
SizeOfHeaders PE文件的所有头部之和大小,是文件对齐整数倍 4Byte 21
CheckSum 系统重要的dll会有,判断文件是否被进行修改 4Byte 22
SizeOfStackReserve 初始化保留栈的大小 4Byte 25
SizeOfStackCommit 初始化时实际提交栈的大小 4Byte 26
SizeOfHeapReserve 初始化保留堆的大小 4Byte 27
SizeOfHeapCommit 初始化时实际提交堆的大小 4Byte 28
Magic字段补充说明

常见的一些Magic字段取值说明,均为小端存储 PE32(10B): [0B 10] PE32+(20B): [0B 20]

程序入口补充说明

真实的入口地址 ==(内存镜像基址)ImageBase+(程序入口地址)AddressOfEntryPoint
其中ImageBase属于相对虚拟地址(RVA),在内存中开始位置距离.程序的首选装载地址,如代码区中注释部分内容所示

对齐相关内容补充

对齐主要包括两大部分内存对齐以及文件对齐

  • 内存对齐

内存对齐原因:
1. 为了程序可移植性,在某些平台只能在特定的地址处访问特定类型的数据,为了更好的兼容不同平台
2. 数据结构(尤其是栈)应该尽可能在自然边界上对齐。
3. 为了访问未对齐的内存,处理器需要作两次内存访问;而未对齐的内存仅需要访问一次

内存对齐原理:先查看C语言代码及其执行结果

#include <stdio.h>

struct test
{
char x1;
short x2;
float x3;
char x4;
}TEST;
struct test2
{
float x1;
short x2;
char x3;
char x4;
}TEST2;
void main()
{   
    test t1;
    test2 t2;
    printf("this test size of : %d\n",sizeof(t1));
    printf("this test start address : %x\n",&t1);
    printf("this test2 size of : %d\n",sizeof(t2));
    printf("this test2 start address : %x\n",&t2);
}

执行结果如下图:


执行结果

可以从结果发现,两个结构体的成员变量都是只有2个char类型,1个short类型,1个float类型,但是得到的结构体大小不一致,这就是由于内存对齐导致的结果
为了探究内存对齐原理,可以通过查看内存地址的数据,以及反汇编调试进行,为了方便,我打出来了相关的存储地址分别为0x0019ff24与0x0019ff1c,通过打断点进行调试分析,并对其进行赋值来观察内存使用情况。

对t1变量在内存中的地址分配分析

首先 根据输出的内存起始地址,找到变量,在执行t1变量声明时,占用了12Byte,并且初始化为CC,就是汉字的"烫"
t1变量声明
其次 逐个对t1变量的成员赋值,并同时观察内存数据
对x1成员进行赋值
当对x2变量进行赋值时发现,并未按照预期想的,紧挨x1变量内存地址赋值,而是跳过1Byte进行赋值,char明明只是占1Byte,但是通过调试容易发现,好像是感觉上占2Byte
对x2成员进行赋值
但是 又发现对x3变量赋值时,并未跳转,紧挨这赋值
对x3成员进行赋值
最后同样的,x4成员赋值也是正常的。
对x4成员进行赋值

通过上面追踪分析,可以发现,这就是产生结果为12Byte的原因。

同样的再次跟踪t2变量,及其成员赋值过程

首先 根据输出的内存起始地址,找到变量,在执行t2变量声明时,占用了8Byte,并且初始化为CC,就是汉字的"烫"
t2变量初始化
由于第一个成员变为float类型所以占据4Byte
对x1成员进行赋值
第二个成员变为short类型所以占据2Byte,且紧挨这第一个成员变量地址赋值
对x2成员进行赋值
由于第三个成员变为char类型紧挨第二个赋值为B
对x3成员进行赋值
最后一个成员依旧紧挨赋值为B
对x4成员进行赋值

通过对比,不难发现,变量声明的顺序会导致结构体大小不一致,第一个结构体变量明显存在未使用的内存空间,从而导致空间浪费。这些都是由于内存对齐机制所导致,机制原理主要是起始的内存地址必须是该类型变量所占内存大小的整数倍,例如t1的x2成员为short占2Byte,所以需要从第2,4,6等2的整数倍地方开始存储数据内存,这就是内存对齐机制。

  • 文件对齐
    文件对齐,主要是用来控制PE扩展头部,后面每一个Section的磁盘对齐的因子,必须遵守扩展为该因子的整数倍。
综上所述PE扩展文件头32位,大小固定且为224Byte,共31大成员字段。其中关键字段成员为以上12大字段成员内容。

继续以Kernel32.dll进行分析


PE扩展头部
字段 数值(小端存储) 含义
Magic 0B01 PE为32位
AddressOfEntryPoint 705F0100 程序入口地址确定为0010F570
ImageBase 0000806B 内存镜像基址为6B800000
SectionAlignment 00000100 内存对齐大小单位为0x00010000H
FileAlignment 00100000 文件对齐大小单位为0x00001000H
SizeOfImage 00000000 PE文件内存展开后大小为0x00000000H
SizeOfHeaders 00000E00 PE文件的所有头部之和大小为0x000E0000H
CheckSum 00100000 校验和为00100000
SizeOfStackReserve 03004041 初始化保留栈的大小0x41400003
SizeOfStackCommit 00000400 实际提交栈的大小为0x00400000
SizeOfHeapReserve 00100000 初始化保留堆的大小0x00001000
SizeOfHeapCommit 00001000 实际提交堆的大小为0x00100000
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容