windows PE Image 文件分析(6)--- .reloc 节与 base relocation table
2013-12-11 21:54
555 查看
.reloc 节和 base relocation table 仅存在于 Image 文件中,用于当映像被加载运行的 ImageBase 改变后,对映像内的使用的地址进行重定位。
需要进行 ImageBase 重定位的映像性能会变得很糟糕。32 位的应用程序在 64 位系统上运行就是一个典型的例子。
下面以前面的 32 位 helloworld.exe 映像为例子
32 位映像的 ImageBase 都被设为 0x00400000,而 64 位映像的 ImageBase 被设为 0x00000001_40000000
注意上面的蓝色粗体部分,实际上这是一条 call 指令的机器代码,这条指令是:
实际上,这就是调用 LoadString() 函数的一条指令,LoadString() 的地址就放在 0x004183C0 地址上。
当映像被加载后的 ImageBase 还是 0x00400000,那么这个映像就不需要 ImageBase 重定位,但是很遗憾,特别是当 32 位程序在 64 位系统上运行时,这个情况就发生。
这个情况下,这个 0x004183C0 地址就会产生错误,加载器需要将它重新重位在:0x012C83C0 地址上。
这个 0x012C83C0 是等于:0x004183C0 - 0x00400000 + 0x012b0000 = 0x012C83C0
计算方法就是得到基于 ImageBase 的偏移量再加上新的 ImageBase 值,这个 0x012C83C0 就是正确的函数地址:
上面就是 visual studio 2010 调试下得出的 call 指令
helloworld.exe 的 .reloc 位置在 0x00428000(ImageBase + VritualAddress),它在映像文件的位置是 0x00015400 占用 0x600 bytes 的文件空间
base relocation table 存放在 .reloc 节里,大小为 0x340 bytes
base relocation table 由 IMAGE_BASE_RELOCATION 结构和它的 Entry 组成
VirtualAddress 是 base relocation table 的位置,它是一个 RVA 值,SizeOfBlock 是 Base Relocation Table 的大小
这个 12 位的 Offset 值是基于 IMAGE_BASE_RELOCATION 结构的 VirtualAddress, 而 VirtualAddress 是基于 ImageBase 的 RVA 值
因此最终的 Offset 值应该是 ImageBase + VirtualAddress + Offset
在 WinNT.h 中定义了 Base Relocation Table 的类型:
大部分的 Base Relocation Table 类型都是 IMAGE_REL_BASED_HIGHLOW 类型,表示被重定位的是 32 位的值。
举个例子,有如下的 Entry 值:
93 34
这个 Entry 是 0x3493,那么 Base Relocation Table 类型是 3 也就是 IMAGE_REL_BASED_HIGHLOW 类型,它的 Offset 值是 0x0493,那么需要重定位的位置在 0x00411493
这个值计算方法是:ImageBase + VirtualAddress + Offset = 0x00400000 + 0x11000 + 0x493 = 0x00411493
第 1 个 base relocation table 的 size 是 0xDC bytes,因此,下一个 base relocation table 就在 0x004280DC 处
下面是使用 dumpbin 得出的 base relocation table 结果:
与 dumpbin 的结果是相符的。
需要进行 ImageBase 重定位的映像性能会变得很糟糕。32 位的应用程序在 64 位系统上运行就是一个典型的例子。
下面以前面的 32 位 helloworld.exe 映像为例子
1. ImageBase 重定位
编译器会为每个映像建立一个首选的 ImageBase 值,ImageBase 是映像被加载运行时所有地址的基地址,因此 ImageBase 显得非常重要。1.1 映像的 ImageBase 值
典型地 helloworld.exe 映像的 ImageBase 被设为:0x00400000OPTIONAL HEADER VALUES 10B magic # (PE32) 10.00 linker version 3C00 size of code 12000 size of initialized data 0 size of uninitialized data 1120D entry point (0041120D) @ILT+520(_wWinMainCRTStartup) 1000 base of code 1000 base of data 400000 image base (00400000 to 00428FFF) 1000 section alignment 200 file alignment 5.01 operating system version 0.00 image version 5.01 subsystem version 0 Win32 version 29000 size of image 400 size of headers 0 checksum 2 subsystem (Windows GUI) |
1.2 映像内的地址使用
下面是从 helloworld.exe 映像中的 .text 节摘下来的数据:00411490: 6A 64 68 00 72 41 00 6A 67 8B 45 08 50 FF 15 C0 jdh.rA.jg.E.P?.à 004114A0: 83 41 00 3B F4 E8 D2 FC FF FF 8B F4 6A 64 68 38 .A.;?èòü??.?jdh8 |
0041149D: FF 15 C0 83 41 00 call dword ptr [004183C0h] |
当映像被加载后的 ImageBase 还是 0x00400000,那么这个映像就不需要 ImageBase 重定位,但是很遗憾,特别是当 32 位程序在 64 位系统上运行时,这个情况就发生。
1.3 ImageBase 重定位
在我的实例中,这一次 helloworld.exe 的运行,ImageBase 被加载到 0x012b0000,没错就需要进行 ImageBase 重定位处理。call dword ptr [004183C0h] |
这个 0x012C83C0 是等于:0x004183C0 - 0x00400000 + 0x012b0000 = 0x012C83C0
计算方法就是得到基于 ImageBase 的偏移量再加上新的 ImageBase 值,这个 0x012C83C0 就是正确的函数地址:
012C14B9 FF 15 C0 83 2C 01 call dword ptr [__imp__LoadStringW@16 (12C83C0h)] |
2. .reloc 节
现在转入正题,看看 helloworld.exe 映像的 .reloc 节,如下表:域 | .reloc 节 |
VirtualSize | 0x00000564 |
VirtualAddress | 0x00028000 |
SizeOfRawData | 0x00000600 |
PointerToRawData | 0x00015400 |
PointerToRelocations | 0 |
PointerToLinenumbers | 0 |
NumberOfRelocations | 0 |
NumberOfLinenumbers | 0 |
Characteristics | 0x42000040 |
3. base relocation table
域 | base relocation bale |
VirtualAddress | 0x00028000 |
size | 0x340 |
base relocation table 由 IMAGE_BASE_RELOCATION 结构和它的 Entry 组成
3.1 IMAGE_BASE_RELOCATION 结构
这个结构在 WinNT.h 的定义为:// // Based relocation format. // typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; } IMAGE_BASE_RELOCATION; typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; |
3.2 Entry 结构
Entry 结构只有一个 WORD 值,它紧跟着 IMAGE_BASE_RELOCATION 结构后面,但是这个 WORD 却分为两个部分:位域 | 位 | 长度 | 描述 |
Type | [15:12] | 4 Bits | 高 4 位用来表示 Base Relocation Table 的类型 |
Offset | [11:0] | 12 Bits | 低 12 位是 RVA 值,指出需要重定位的位置 |
因此最终的 Offset 值应该是 ImageBase + VirtualAddress + Offset
在 WinNT.h 中定义了 Base Relocation Table 的类型:
// // Based relocation types. // #define IMAGE_REL_BASED_ABSOLUTE 0 #define IMAGE_REL_BASED_HIGH 1 #define IMAGE_REL_BASED_LOW 2 #define IMAGE_REL_BASED_HIGHLOW 3 #define IMAGE_REL_BASED_HIGHADJ 4 #define IMAGE_REL_BASED_MIPS_JMPADDR 5 #define IMAGE_REL_BASED_MIPS_JMPADDR16 9 #define IMAGE_REL_BASED_IA64_IMM64 9 #define IMAGE_REL_BASED_DIR64 10 |
举个例子,有如下的 Entry 值:
93 34
这个 Entry 是 0x3493,那么 Base Relocation Table 类型是 3 也就是 IMAGE_REL_BASED_HIGHLOW 类型,它的 Offset 值是 0x0493,那么需要重定位的位置在 0x00411493
这个值计算方法是:ImageBase + VirtualAddress + Offset = 0x00400000 + 0x11000 + 0x493 = 0x00411493
4. helloworld.exe 映像的 Base Relocation Table
00428000 00 10 01 00 // VirtualAddress = 0x00011000 00428004 DC 00 00 00 // SizeOfBlock = 0x000000DC // Entries 00428008 93 34 // type = 3, offset = 493 0042800A 9F 34 // type = 3, offset = 49F 0042800C AF 34 // type = 3, offset = 4AF 0042800E BB 34 // type = 3, offset = 4BB 00428010 F4 34 // type = 3, offset = 4F4 00428012 10 35 // type = 3, offset = 510 00428014 2F 35 // type = 3, offset = 52F 00428016 46 35 // type = 3, offset = 546 00428018 59 35 // type = 3, offset = 559 0042801A 6F 35 // type = 3, offset = 56F 0042801C 94 35 // type = 3, offset = 594 0042801E A0 35 // type = 3, offset = 5A0 ... ... 004280DC 00 20 01 00 // VirtualAddress = 0x00012000 004280E0 20 01 00 00 // SizeOfBlock = 0x00000120 004280E4 0C 30 // type = 3, offset = 00C 004280E6 15 30 // type = 3, offset = 015 004280E8 1E 30 // type = 3, offset = 01E 004280EA 23 30 // type = 3, offset = 023 004280EC 4D 30 // type = 3, offset = 04D 004280EE 57 30 // type = 3, offset = 057 ... ... |
下面是使用 dumpbin 得出的 base relocation table 结果:
BASE RELOCATIONS #7 11000 RVA, DC SizeOfBlock 493 HIGHLOW 00417200 ?szTitle@@3PA_WA (wchar_t * szTitle) 49F HIGHLOW 004183C0 __imp__LoadStringW@16 4AF HIGHLOW 00417138 ?szWindowClass@@3PA_WA (wchar_t * szWindowClass) 4BB HIGHLOW 004183C0 __imp__LoadStringW@16 4F4 HIGHLOW 004183C4 __imp__LoadAcceleratorsW@8 510 HIGHLOW 004183C8 __imp__GetMessageW@16 52F HIGHLOW 004183CC __imp__TranslateAcceleratorW@12 546 HIGHLOW 004183D0 __imp__TranslateMessage@4 559 HIGHLOW 004183D4 __imp__DispatchMessageW@4 56F HIGHLOW 00411590 594 HIGHLOW 00411598 5A0 HIGHLOW 004115A4 ... ... 12000 RVA, 120 SizeOfBlock C HIGHLOW 00417734 ___native_startup_state 15 HIGHLOW 00417734 ___native_startup_state 1E HIGHLOW 00415618 ___xi_z 23 HIGHLOW 0041530C ___xi_a 4D HIGHLOW 0041733C 57 HIGHLOW 00417734 ___native_startup_state |
版权 mik 所有,转载请注明出处
相关文章推荐
- windows PE Image 文件分析(5)--- .rsrc 节与 resource table
- MySql中使用Sql语句修改表的结构(不断更新)
- 《卖油翁》
- 【sql server 2008】1433端口开启解决方案
- LeetCode Remove Element
- windows PE Image 文件分析(4)--- 导入函数的绑定
- windows PE Image 文件分析(3)--- .idata 节与 import table
- srand()使用误区
- LTE
- automake安装出错
- Linux程序设计笔记第八章 MySQL
- 唠唠“朋友”
- windows PE Image 文件分析(2)--- .text 节
- Hibernate 关系映射 总结整理
- TCP/IP详解--TCP传输小数据包效率问题
- 汇编程序的CMPSB CMPSW CMPSD的使用
- POJ 1787 Charlie's Change (完全背包/多重背包,输出方案的物品个数)
- 影像质量评价指标汇总
- 问题:配置在服务器上的网站上无法使用media播放音频文件
- mysql简单命令