| 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
根据公式也能推回去,就不写了