一、简介
PE
(Portable Executable
)文件格式是在Windows操作系统下的一种32
位的可移植、可执行文件格式。在学习PE
文件格式的过程中,也可以梳理优化进程、内存、DLL
等内容,它们是Windows
操作系统最核心的部分。值得我们花时间去消化。根据PE
正式规范,将PE
文件分为一下种类;
二、PE文件内容映射
1、PE文件内容
下面以windows
系统路径“C:\Windows\System32
”中的"cmd.exe
"为例,开始讲解PE
文件格式的基本结构,以十六进制方式查看"cmd.exe
"文件,部分内容如下图所示:
2、PE文件内容映射到内存
PE
文件内容映射都内存时的情况如下图所示;文件中的内容可分为代码节区(“.text
”)、数据节区(“.data
”)、资源节区(“.rsrc
”)等别分保存在不同位置;各个节区头定义了对应节区在文件或内存中的大小,位置,属性等;
值得注意的是:
(1) 在文件中使用偏移(offset
)来表示位置;
(2) 在内存中使用虚拟地址(VA:Virtual Address
)来表示位置。
(3) PE头与各节区尾部都存在一个NULL
填充(null padding
)区域.目的是通过使用“最小基本单位”的概念,让内存或文件中的位置都落在最小单位的倍数上;这样即可以让计算机提高内存中,内存,网络包的处理效率;也可以提高处理文件中数据的效率;
3、PE文件内容映射到内存后的定位
3.1 前言
在理解如果定位前,我们需要理解如下单词含义
ImageBase:表示基准地址,表示PE文件(DLL
文件为主)加载到进程的虚拟内存时的特定位置;
VA:表示虚拟地址(Virtual Address
),指的是进程虚拟内存中的绝对地址;
RVA:表示相对虚拟地址(Relative Virtual Adress
),指的是从某个基准位置(ImageBase)开始的相对地址;
VA与RVA满足如下关系式: VA = RVA + ImageBase
3.2 机器码定位讲解( RVA to FOA)
在PE
文件(dll
为主)加载到内存时,往往会遇到重定位(Relocaiton)
的问题,可能导致加载位置与文件中预定的加载位置不同而定位失败;为了解决这个问题,PE
文件头信息中的地址使用的是RVA
(Relative Virtual Adress
);这样即使基准位置ImageBase
改变,只要相对于基准位置的相对偏移没有变化,就能正常访问到指定信息。
遵循关系式: VA = RVA + ImageBase
;
遵循关系式:FOA - PointerToRawData = RVA
核心等价关系:文件中 与 内存中的机器码相对于节区起始地址的偏移相等
通俗地说就是某特定代码相对于自己节区起始地址的位置,在映射到内存后是不变的;
3.3 机器码定位举例(已上图为依据举例)
举例1:若已知内存中指定机器码的RVA = 1500
,求文件中机器码的offset
(FOA:file Offset Address
).
解:设机器码在文件中偏移为x. 首先查RVA所属内存中的节区为“
.text
”,因为1000 < 1500 < 2000
;
(其中ImageBase = 01000000
); 然后计算机器码相对内存中节区起始地址的偏移:内存_offset = 1500 - 1000 = 500
;(“.text
”节区在内存起始地址为1000
)
最后计算机器码相对文件中节区起始地址的偏移:文件_offset = x - 400
;
(“.text
"节区在文件起始地址为400
) 根据等价关系内存_offset = 文件_offset
;求得 `500 = x
- 400; 最终 x = 900`;
举例2:若已知内存中指定机器码的RVA = 4100
,求文件中机器码的offset
(FOA:file Offset Address
).
解:设机器码在文件中偏移为x.
首先查RVA所属内存中的节区为“.rsrc
”,因为4000 < 4100 < C000
;(其中ImageBase = 01000000
);
然后计算机器码相对内存中节区起始地址的偏移:内存_offset = 4100 - 4000 = 100
;(“.text
”节区在内存起始地址为4000
)
最后计算机器码相对文件中节区起始地址的偏移:文件_offset = x - 2E00
;
(“.text
"节区在文件起始地址为2E00
) 根据等价关系内存_offset = 文件_offset
;求得100 = x - 2E00; 最终 x = 2F00
;
举例3:如下图所示,使用IDA
打开cmd.exe
文件查看内存中的机器码时,已知机器码的地址是0x14005900
,求相同机器码在文件中的地址;
由图可知:设地址为x. 节区“
.pdata
”在内存中的起始地址是59000
;(Virtual address = 59000
)
节区“.pdata”在文件中的起始地址是3BC00
;
RVA = VA - ImagBase = 0x140059000 -0x140000000 = 59000
由于内存_offset = 59000 - 59000 = 0
所以文件_offset = X - 3BC00 = 0
; 最后的x = 3BC00
三、小结
熟悉PE文件于内存之间的映射关系,可以帮助我们在逆向过程中,快速定位机器码的位置。是一项非常基础且必不可少的知识点。同样的原理拓展后,我们还可以在逆向过程中快速将动态分析(x32dbg为主)和静态分析(IDA为主)的机器码匹配关联,快速跟踪分析问题。值得我们花时间去瞧瞧哈。