能力值:
( 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
能力值:
( 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; }
能力值:
( LV2,RANK:10 )
4 楼
哪请问一下
如果逆转过来是不是就是Offset转化为RVA了呢?
事实上这样
我尝试在一个EXE文件的节空隙中写入了一段代码
然后我给他添加导出表导出这段代码来给我自己使用
问题在于我在导出表中填的值在加载到虚拟内存后无法使用
发生内存访问违规
能力值:
( LV2,RANK:10 )
5 楼
你插入代码就把后面代码的 RVA 改变了
需要重定位
能力值:
( 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地址开始的地方,如果想搬到别的地方去执行,就必须对访问全局变量的指令进行修正,这就是重定位的问题
能力值:
( 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有提供这个函数来转换.调用就行了.