日期:2014-05-17 浏览次数:20661 次
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; }