PE文件里RVA比文件中的实际地址大0x10000,参考下图,这时用UE查看一个PE的内容.idata段的RVA(0x19000)比直接的指针(0x9000)大了0x10000,.idata段实际在0x9000的位置上,能告诉我为什么吗

解决方案 »

  1.   

    RVA是相对虚拟地址,是相对文件加载地址的。
    另外,看不到图。
      

  2.   

    贴图功能有点问题吧
    图片在这里
    http://lh4.ggpht.com/_GWhYFn-Ueds/SVjT9PYrB6I/AAAAAAAABEA/ImQ0BUfl8sg/Address.JPG
      

  3.   

    所谓PE文件的相对虚拟地址(Relative Virual Address,RVA):是PE文件中的数据、模块等运行在内存中的实际地址相对PE文件装载到内存的基地址之间的距离。举例说明,如果PE文件装入虚拟地址(VA)空间的400000h处,且进程从虚址401000h开始执行,我们可以说进程执行起始地址在RVA 1000h。引用看雪学院《加密与解密II》PE文件格式小节中的一段话:“…对于PE文件,首先应该知道,磁盘中的执行文件与其被Windows装载程序装入后的Module看起来非常相似。Windows装载程序把磁盘文件编程实际执行代码的中作相当简单,装载程序使用文件内存映象机制将磁盘文件映射到虚拟地址空间。打个比方,PE文件象一个活动地房子,装载时只需将某个块放在某个地方,在把它和其它部分拧好即可(比如说,把它和DLL连结在一起)。加载PE文件格式的DLL同样的简单。一旦Module被装入,在Windows中就同其它已经装入的文件一样了。”我是这样理解这段话的:它说明PE文件中的节等模块加载到内存时,节的数据布局和文件中的内存布局基本保持不变。所以可以根据这个数据尺寸相对不变的特点来由RVA正确换算出到数据相对文件的偏移。即,每个节(section)中的数据的起始位置相对节的起始位置是不变的,不管节是在文件中还是被加载到内存中。===========================
    下面是具体代码演示
    首先, 在分析Coff Header的时候,  保存Section Header
    到std::vector<PIMAGE_SECTION_HEADER> m_vSectionHeaders;
    // read the section headers
    m_vSectionHeaders.clear();
    for( int i = 0; i < m_pCoffHeader->NumberOfSections; i++)
    {
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)m_pDotNetPEFile->GetCurrentMemoryPointer();
    m_pDotNetPEFile->MoveCursorForward(sizeof(IMAGE_SECTION_HEADER));
    m_vSectionHeaders.push_back(pSectionHeader);
    }
    RVA只是相对虚拟地址, 是程序加载后的映射地址,
    然后,根据RVA就能获取到Offset
    DWORD CPEFileHeader::GetOffsetFromRVA(DWORD dwRva)
    {
    std::vector<PIMAGE_SECTION_HEADER>::iterator iter;
    for( iter = m_vSectionHeaders.begin(); iter != m_vSectionHeaders.end(); iter++)
    {
    if((*iter)->VirtualAddress <= dwRva &&
    ((*iter)->VirtualAddress + (*iter)->SizeOfRawData) > dwRva )
    {
    return (*iter)->PointerToRawData + (dwRva - (*iter)->VirtualAddress);
    }
    }
    CDotNetPEFileException::Throw(_T("Can not find the offset via GetOffsetFromRVA()."));
    return 0UL;
    }
      

  4.   

    前一个是内存中的块RVA
    后一个是文件中块偏移因为PE并不是完全按照文件中块的offset来映射的,块在内存中的offset跟文件中的offset是不一样的但是,文件中的高地址块一定是映射到内存中的高地址处
      

  5.   

    这个看看吧,稍微有点长
    http://msdn.microsoft.com/en-us/magazine/cc301805.aspx