pe格式从入门到图形化显示(五)-RVA和FOA



前言

通过分析和解析Windows PE格式,并使用qt进行图形化显示


一、什么是Windows PE格式中的RVA和FOA?

PE文件格式的RVA(相对虚拟地址)和FOA(文件偏移地址)是用于描述文件在内存和磁盘中的位置的概念。

RVA是相对于PE文件载入地址的偏移位置,它是一个相对的地址(偏移)。当PE文件在磁盘中时,某个数据位置相对于文件头的偏移量称为文件偏移地址(FOA)。

RVA在程序加载到内存时被使用,它指向程序在内存中的虚拟地址。FOA在程序未加载到内存时被使用,它指向程序在磁盘上的文件偏移量。

二、RVA和FOA互相转换

1.转换数据结构体

struct RVA2FOAInfo
{
    QString sectionName;
    DWORD FOA = 0;
    DWORD VA = 0;
    DWORD RVA = 0;
};

2.RVA转FOA

RVA2FOAInfo PEParser::RVA2FOA(DWORD rva)
{
    RVA2FOAInfo info;
    //如果内存对齐大小等于文件对齐大小,FOA==RVA
    if (m_sectionAlignment == m_fileAlignment)
    {
        info.VA = m_imageBase + rva;
        info.RVA = info.FOA = rva;
        return info;
    }
    //如果RVA在PE头部,FOA==RVA
    DWORD headerSize = sizeof(IMAGE_DOS_HEADER) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
    if (m_x86Flag)
    {
        headerSize += sizeof(IMAGE_OPTIONAL_HEADER32);
    }
    else
    {
        headerSize += sizeof(IMAGE_OPTIONAL_HEADER64);
    }
    headerSize += sizeof(IMAGE_SECTION_HEADER) * m_fileHeader.NumberOfSections;
    if (rva <= headerSize)
    {
        info.VA = m_imageBase + rva;
        info.RVA = info.FOA = rva;
        return info;
    }
    for (int i = 0; i < m_sections.size(); ++i)
    {
        //判断RVA处在哪个节中
        if (rva >= m_sections[i].VirtualAddress && rva < (m_sections[i].VirtualAddress + m_sections[i].SizeOfRawData))
        {
            info.VA = m_imageBase + rva;
            info.RVA = rva;
            info.FOA = rva - m_sections[i].VirtualAddress + m_sections[i].PointerToRawData;
            info.sectionName = QString::asprintf("%s", m_sections[i].Name);
        }
    }
    return info;
}

3.FOA转RVA

RVA2FOAInfo PEParser::FOA2RVA(DWORD foa)
{
    RVA2FOAInfo info;
    //如果内存对齐大小等于文件对齐大小,FOA==RVA
    if (m_sectionAlignment == m_fileAlignment)
    {
        info.VA = m_imageBase + foa;
        info.RVA = info.FOA = foa;
        return info;
    }
    //如果RVA在PE头部,FOA==RVA
    DWORD headerSize = sizeof(IMAGE_DOS_HEADER) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
    if (m_x86Flag)
    {
        headerSize += sizeof(IMAGE_OPTIONAL_HEADER32);
    }
    else
    {
        headerSize += sizeof(IMAGE_OPTIONAL_HEADER64);
    }
    headerSize += sizeof(IMAGE_SECTION_HEADER) * m_fileHeader.NumberOfSections;
    if (foa <= headerSize)
    {
        info.VA = m_imageBase + foa;
        info.RVA = info.FOA = foa;
        return info;
    }
    for (int i = 0; i < m_sections.size(); ++i)
    {
        //判断FOA处在哪个节中
        if (foa >= m_sections[i].PointerToRawData && foa < (m_sections[i].PointerToRawData + m_sections[i].SizeOfRawData))
        {
            info.RVA = foa - m_sections[i].PointerToRawData + m_sections[i].VirtualAddress;
            info.VA = m_imageBase + info.RVA;
            info.FOA = foa;
            info.sectionName = QString::asprintf("%s", m_sections[i].Name);
        }
    }
    return info;
}

相关推荐

  1. pe格式入门图形显示)-RVAFOA

    2024-04-09 17:50:03       37 阅读
  2. pe格式入门图形显示(四)-节表

    2024-04-09 17:50:03       38 阅读
  3. Python入门精通秘籍

    2024-04-09 17:50:03       63 阅读
  4. 【go入门精通】forfor range的区别

    2024-04-09 17:50:03       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-09 17:50:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-09 17:50:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-09 17:50:03       87 阅读
  4. Python语言-面向对象

    2024-04-09 17:50:03       96 阅读

热门阅读

  1. 记一个Unity的异常问题

    2024-04-09 17:50:03       37 阅读
  2. UVA10391 Compound Words 复合词 解题报告

    2024-04-09 17:50:03       29 阅读
  3. Python入门:轻松学习,编程不再难

    2024-04-09 17:50:03       36 阅读
  4. 云智前端面试题

    2024-04-09 17:50:03       32 阅读
  5. 服务器硬件基础知识解析

    2024-04-09 17:50:03       31 阅读
  6. Vue.nextTick() 使用场景及实现原理

    2024-04-09 17:50:03       38 阅读
  7. DockerFile定制镜像

    2024-04-09 17:50:03       32 阅读
  8. Vue3 · 小白学习全局 API:常规

    2024-04-09 17:50:03       38 阅读
  9. 面试前必看,仅供参考

    2024-04-09 17:50:03       34 阅读