RVA与FOA的转换
RVA与FOA的转换
想象一下,如果你想通过逆向的方式改变一个全局变量的初始值,该怎么做?首先我们可以写一个程序,输出一个全局变量的地址和值:
int a = 0x 12345678;
int main(){
printf("Address: 0x%x \n",&a);
printf("Value:0x%x \n",a);
getchar();
return 0;
}

我们运行程序可以看见相应的值,那么我们可以是否可以在文件中直接搜索对应的值然后修改呢?这种方法没有毛病,但是文件中也许会存在很多个0x12345678,你无法准确的知道哪一个才是全局变量;那么,又是否可以通过已经给出的这个地址0x42ba30直接去寻找呢?当然也是不行的,因为在之前章节的学习中我们了解到,PE文件有2种状态(动静态),在这2种状态下,文件的对齐方式会发生变化,所以当前的地址是PE文件运行时(动态)的地址,你需要转换成在磁盘上(静态)的地址。

这两种状态的地址相互转换,我们可以称之为RVA与FOA的转换,RVA就是相对虚拟地址(运行时的位置),FOA就是文件偏移地
址(磁盘静态的位置);从RVA转换到FOA,就是从文件运行时(动态)的地址转换成在磁盘上(静态)的地址,按如下公式可以
进行转换:
第一步:RVA地址由内存地址减去ImageBase地址(PE文件在内存中的开始位置是由扩展PE头中的ImageBase决定);
第二部 判断RVA地址是否位于PE头中:
a.如果是,那么RVA等于FOA;
b.如果不是,判断RVA在哪个节
i. 当满足RVA地址大于等于节.VirtualAddress和RVA地址小于等于.VirtualAddress加上当前节内存对齐后的大小,就表示RVA地址在该节中。
ii. RVA地址减去节.VirtualAddress等于差值,FOA地址就是根据.PointerToRawData加上差值。
在一些较老的编译器中,编译出来的文件会区分文件对齐、内存对齐,但是在现在的编译器编译出来的程序,
文件对齐与内存对齐时完全一样的,所以我们不用费这么大的周折,我们只需要算出RVA的值就可以得出FOA
的值。
例如,在当前程序中就是这样,根据0x42BA30-0x400000(ImageBase)得出0x2BA30,其是RVA,也是FOA,直
接使用Winhex打开找到:

可以直接修改它然后保存运行,这时候你就会发现全局变量的值已经发生了改变:

浙公网安备 33010602011771号