首页
社区
课程
招聘
[求助]关于Offset与RVA之间的关系
发表于: 2009-7-12 04:23 11141

[求助]关于Offset与RVA之间的关系

2009-7-12 04:23
11141

一直没有弄明白在PE文件中的Offset(文件偏移)如何转换成Rva(相对虚拟地址)
很想请各位朋友们给我详细讲解下好么?
先谢过各位了


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 546
活跃值: (1672)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
2
1.文件偏移地址 (File Offest)
数据在PE文件中的地址叫文件偏移地址,个人认为叫做文件地址更加准确.这是文件在磁盘上存放时相

对文件开头的偏移.

2.装载地址 (Image Base)
PE装入内存时的基地址.默认情况下,EXE文件在内存中的基地址是0x00400000,DLL文件是0x10000000.

这些位置可以通过修改编译选项更改.

3.虚拟内存地址 (Virtual Address,VA)
PE文件中的指令被装入内存后的地址.

4.相对虚拟地址 (Relative Virtual Address,RVA)
相对虚拟地址是内存地址相对于映射基质的偏移量.

虚拟内存地址,映射基质,相对虚拟内存地址三者之间有如下关系.

VA=Image Base + RVA
2009-7-12 06:12
0
雪    币: 179
活跃值: (26)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
PE文件无论是在物理文件中或者是映射入内存以后,每一节中的内容相对于节开始的相对位置
都是相同的。在物理文件中这个值是IMAGE_SECTION_HEADER.SizeOfRawData,在虚拟内存中这个值为RVA。
这个是将RVA转换为Offset的函数,pFileMap是传进来的文件的字符串指针,RVA是虚拟地址偏移,返回Offset。楼主可以参考下。
int RVAToOffset(char *pFileMap, DWORD RVA)
{
        char *buff=pFileMap;
        int rva=RVA;
        IMAGE_DOS_HEADER *idh2;
        IMAGE_NT_HEADERS *inh2;
        IMAGE_SECTION_HEADER *ish2;

        idh2=(IMAGE_DOS_HEADER*)buff;
        inh2=(IMAGE_NT_HEADERS*)(buff+idh2->e_lfanew);
       
        int i=inh2->FileHeader.NumberOfSections;
        for(int j=0;j<i;j++)
        {
                ish2=(IMAGE_SECTION_HEADER*)(buff+idh2->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*j);
                if(rva>=(ish2->VirtualAddress))
                {
                        int off=ish2->VirtualAddress+ish2->SizeOfRawData;
                        if(rva<off)
                        {
                                off=rva-ish2->VirtualAddress+ish2->PointerToRawData;
                                return off;
                        }
                }
        }
        return rva;

}
2009-7-12 13:18
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
哪请问一下
如果逆转过来是不是就是Offset转化为RVA了呢?
事实上这样
我尝试在一个EXE文件的节空隙中写入了一段代码
然后我给他添加导出表导出这段代码来给我自己使用
问题在于我在导出表中填的值在加载到虚拟内存后无法使用
发生内存访问违规
2009-7-15 12:23
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
你插入代码就把后面代码的  RVA 改变了
需要重定位
2009-7-15 16:44
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
这贴怎么给了关注拉?

rva相当于offset的offset , 内存地址偏移量的偏移量

如果把00401000作为基址 000401001 的RVA是1
用内存地址减去内存基址
000401001 - 00401000 = 1

00401000 到 NNNNNNNN 都是offset
用NNNNNNNN - 00400000 = RVA

下面一个老罗的代码的重定位问题的例子
如果你能根据2楼跟我讲的明白offset 跟rva 区别
并看懂下面的例子就彻底明白了offset 跟rva了

代码的重定位问题可以用下面的例子来说明:

dwVar           dd      ?

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Proc1       proc        _dwParam

                local   @dwLocal

                mov     eax,dwVar

                mov     eax,@dwLocal

                mov     eax,_dwParam

                ret

Proc1       endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                invoke  Proc1,1234

代码中包括了调用子程序,存取全局变量、局部变量和参数的情况,经过编译链接以后再反汇编,就成了下面的样子:

:00400FFC 0000                              ;dwVar变量

:00401000 55              push ebp

:00401001 8BEC           mov ebp, esp

:00401003 83C4FC         add esp, FFFFFFFC

:00401006 A1FC0F4000     mov eax, dword ptr [00400FFC]   ;mov eax,dwVar

:0040100B 8B45FC         mov eax, dword ptr [ebp-04]     ;mov eax,@dwLocal

:0040100E 8B4508         mov eax, dword ptr [ebp+08]     ;mov eax,_dwParam

:00401011 C9              leave

:00401012 C20400         ret 0004

:00401015 68D2040000     push 000004D2

:0040101A E8E1FFFFFF     call 00401000                   ;invoke Proc1,1234

分析一下机器码就可以发现,存取全局变量的指令mov eax,dwVar中,全局变量的地址是包含在机器码中的(指令的机器码是A1FC0F4000,第一个字节A1h是mov eax,xxx的机器码,后面的FC0F4000按照高字节在后的顺序读就是变量的地址00400FFCh);存取局部变量和参数的指令中并不包含绝对地址;call指令中的地址数据也是相对的,所以,当这段机器码从00401000h地址被搬到00801000h处的时候,就成了下面的样子:

:00800FFC 0000

:00801000 55              push ebp

:00801001 8BEC           mov ebp, esp

:00801003 83C4FC         add esp, FFFFFFFC

:00801006 A1FC0F4000     mov eax, dword ptr [00400FFC]   ;mov eax,dwVar

:0080100B 8B45FC         mov eax, dword ptr [ebp-04]     ;mov eax,@dwLocal

:0080100E 8B4508         mov eax, dword ptr [ebp+08]     ;mov eax,_dwParam

:00801011 C9              leave

:00801012 C20400         ret 0004

:00801015 68D2040000     push 000004D2

:0080101A E8E1FFFFFF     call 00801000                   ;invoke Proc1,1234

这时候,A1FC0F4000机器码还是被解释为存取00400FFCh地址,而实际的变量地址已经被搬到00800FFCh处了,这就是说,指令存取的是错误的地址,所以这段指令要想正常执行,就必须放在00401000h地址开始的地方,如果想搬到别的地方去执行,就必须对访问全局变量的指令进行修正,这就是重定位的问题
2009-7-15 20:25
0
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
ImageRvaToVa
The ImageRvaToVa function locates a relative virtual address (RVA) within the image header of a file that is mapped as a file and returns the virtual address of the corresponding byte in the file.

PVOID ImageRvaToVa(
  PIMAGE_NT_HEADERS NtHeaders,
  PVOID Base,
  ULONG Rva,
  PIMAGE_SECTION_HEADER *LastRvaSection  
);

ms有提供这个函数来转换.调用就行了.
2009-8-4 12:11
0
游客
登录 | 注册 方可回帖
返回
//