「基础学习」VA与FOA的转换
2023-11-12 11:16:24 Author: 黑客在思考(查看原文) 阅读量:3 收藏

VA_IMAGE_SECTION_HEADER.VirtualAddressVirtual Address在内存中的虚拟地址
RVA_IMAGE_SECTION_HEADER.VirtualAddressRelative Virtual Address相对虚拟地址
FOA_IMAGE_SECTION_HEADER.PointerToRawDataFile 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,查看调试试图的模块选项,发现ImageBase0x00f30000

那么RVA=0xF4A8B0(VA)-0xf30000(ImageBase),结果就是0x1A8B0

接着查看区段的Virtual Address:


判断RVA属于哪个段里面,(当然我们知道全局变量在data段中),判断方法是:

RVA>=节.VirtualAddress

RVA<节.VirtualAddress + 当前节内存对齐后的大小=节.VirtualAddress +[(Max{节.Misc,节.SizeOfRawData})÷SectionAlignment]向上取整×SectionAlignment

  • 节.SizeOfRawData是节文件对齐后的大小
  • 节.Misc是节的实际大小

内存对齐后的大小 = [Max{实际的大小,文件对齐后的大小}÷内存对齐]向上取整×内存对齐

  1. 首先0x1A8B0在第三个段之后,因为第三个.data段是0x1A000
  2. 接下来看第二个条件:RVA<节.VirtualAddress + 当前节内存对齐后的大小

节的实际大小 = 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 - 节.PointerToRawData

2.RVA = 差值 + 节.VirtualAddress(RVA) 

3.VA = ImageBase + RVA

根据公式也能推回去,就不写了




文章来源: http://mp.weixin.qq.com/s?__biz=MzI5NzU0MTc5Mg==&mid=2247484982&idx=2&sn=0cf72a49b07848679612cf8ff826078a&chksm=ecb2cff9dbc546efe7310605502c25ba1916b2ac845ba7ef7ab57612944bd4649c24275ac0dc&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh