读书人

PE 基础求解解决办法

发布时间: 2012-05-24 11:55:41 作者: rapoo

PE 基础求解
将RVA转换为File Offset,给大家一个非常经典的公式:
设:VK为相对虚拟地址RVA与文件偏移地址File Offset的差值
VA=ImageBase+RVA
File Offset = RVA ---VK
File Offset = VA---ImageBase---VK


这个里面 VK 怎么知道?

[解决办法]
贴一段我当年写的代码

C/C++ code
extern vector<Section_Header*> *sh_table;extern vector<Import_Table*> *it_table;extern Pe_Header *ph;/* RVA即(Relative Virtual Address)相对与可执行文件加载地址的虚拟地址。* VA即(Virtual Address)虚拟地址,即可执行文件在加载到内存中的地址。* 偏移量则为可执行文件存在磁盘上的偏移地址。** 由于在磁盘上与内存中有不同的对齐方式,因此在第一个段之后,RVA与文件偏移不同。* 在第一个段之前,RVA与偏移地址是相同的。** 因此,在分析一个没被Loader加载到内存的可执行文件映像,需要计算RVA。* RVA计算方法* 1. 遍历可执行文件中的每一个段,根据各个段的起始RVA(IMAGE_SECTION_HEADER->VirtualSize),*    以及该段的原始大小(IMAGE_SECTION_HEADER->SizeOfRawData),计算该段结束RVA。** 2. 测试欲计算的RVA,在哪一个段中,找到后,用应计算RVA减去该段起始RVA,得到相对于该段起始RVA*    的偏移RVA。** 3. 在段表中获取该段的文件所属偏移,加上上一步得到的偏移RVA,即欲计算的目标RVA的偏移地址。*/DWORD RvaToVa(DWORD rva){    static DWORD (*sections)[3] = NULL;    //设置为static变量,目的在于对于一个可执行文件,    //只计算一次各段的起始地址、段尾地址、以及原始指针数组    //However,I do not know why I set the type to a pointer to a array of three DWORDs,    //but just a original array of three DWORDs.    DWORD numberOfSection = ph->GetSectionNumber ();    if (sections == NULL){        sections = new DWORD[numberOfSection][3] ;        for (DWORD i = 0;i < numberOfSection; i++)        {            sections[i][0] = (*sh_table)[i]->VirtualAddress;            //sections[i][0]:段的起始RVA:VirtualAddress            sections[i][1] = (*sh_table)[i]->SizeOfRawData + sections[i][0];            //sections[i][1]:段尾:VirtualAddress + SizeOfRawData            sections[i][2] = (*sh_table)[i]->PointerToRawData;            //sections[i][3]:段原始偏移指针: PointerToRawData        }    }    for (DWORD i = 0;i < numberOfSection;i++)    {        if ( rva > sections[i][0] && rva < sections[i][1] ){            DWORD va = rva - sections[i][0];            va += sections[i][2];            return va;        }    }    return -1;} 

读书人网 >windows

热点推荐