文章目录
- 前言
- [一、什么是Windows PE格式中的RVA和FOA?](#一、什么是Windows PE格式中的RVA和FOA?)
- 二、RVA和FOA互相转换
前言
通过分析和解析Windows PE格式,并使用qt进行图形化显示
一、什么是Windows PE格式中的RVA和FOA?
PE文件格式的RVA(相对虚拟地址)和FOA(文件偏移地址)是用于描述文件在内存和磁盘中的位置的概念。
RVA是相对于PE文件载入地址的偏移位置,它是一个相对的地址(偏移)。当PE文件在磁盘中时,某个数据位置相对于文件头的偏移量称为文件偏移地址(FOA)。
RVA在程序加载到内存时被使用,它指向程序在内存中的虚拟地址。FOA在程序未加载到内存时被使用,它指向程序在磁盘上的文件偏移量。
二、RVA和FOA互相转换
1.转换数据结构体
cpp
struct RVA2FOAInfo
{
QString sectionName;
DWORD FOA = 0;
DWORD VA = 0;
DWORD RVA = 0;
};
2.RVA转FOA
cpp
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
cpp
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;
}