VA | _IMAGE_SECTION_HEADER.VirtualAddress | Virtual Address | 在内存中的虚拟地址 |
RVA | _IMAGE_SECTION_HEADER.VirtualAddress | Relative Virtual Address | 相对虚拟地址 |
FOA | _IMAGE_SECTION_HEADER.PointerToRawData | File Offset Address | 文件偏移地址 |
示例,全局变量程序
#include <stdio.h>int global = 0x610;
int main(int argc, char* argv[])
{
//输出全局变量地址
printf("address:%X\n", &global);
//输出全局变量的值
printf("value:0x%X\n", global);
//暂停一下,防止窗口运行完自动关闭
getchar();
return 0;
}
运行结果:
现在定位global
这个VA0xF4A8B0
,对应的FOA
1.计算RVA 公式: VA - ImageBase = RVA 2.计算差值偏移: RVA - 节.VirtualAddress = 差值偏移.
3.计算FOA : 差值偏移 + 节.PointerToRawData = FOA
首先根据公式换算一下RVA
,查看调试试图的模块选项,发现ImageBase
为0x00f30000
那么RVA=0xF4A8B0
(VA)-0xf30000
(ImageBase),结果就是0x1A8B0
接着查看区段的Virtual Address:
判断RVA属于哪个段里面,(当然我们知道全局变量在data段中),判断方法是:
RVA>=节.VirtualAddressRVA<节.VirtualAddress + 当前节内存对齐后的大小=节.VirtualAddress +[(Max{节.Misc,节.SizeOfRawData})÷SectionAlignment]向上取整×SectionAlignment
内存对齐后的大小 = [Max{实际的大小,文件对齐后的大小}÷内存对齐]向上取整×内存对齐
0x1A8B0
在第三个段之后,因为第三个.data段是0x1A000
节的实际大小 = Virtual Size = 0x12E4
文件对齐后的大小 = Raw Size = 0xA00
所以,Max{节.Misc,节.SizeOfRawData} = 0x12E4
SectionAlignment
是内存对齐粒度为:
那么最终公式为:
内存对齐后的大小 = (0x12E4
÷0x1000
)向上取整 × 0x1000
= 0x2000
所以RVA=0x1A8B0
RVA >= 0x1A000
RVA < 0x1A000
+ 0x2000
= 0x1C000
所以说,这个RVA在.data段中,接着计算差值偏移
0x1A8B0
(RVA) - 0x1A000
(data段的Virtual Address) = 0x8B0
(差值偏移)
0x8B0
(差值偏移) + 0x18200
(data段的Raw Address) = 0x18AB0
(FOA)
然后尝试修改这里的FOA对应的值为
再次运行程序发现成功修改
1.差值 = FOA - 节.PointerToRawData2.RVA = 差值 + 节.VirtualAddress(RVA)
3.VA = ImageBase + RVA
根据公式也能推回去,就不写了