PE文件RV转FOA及FOA转RVA
/************************************************************************/ /* 功能:虚拟内存相对地址和文件偏移的转换 参数:stRVA: 虚拟内存相对偏移地址 lpFileBuf: 文件起始地址 返回:转换后的文件偏移地址 */ /************************************************************************/ size_t RVAToOffset(size_t stRVA, PVOID lpFileBuf) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuf; size_t stPEHeadAddr = (size_t)lpFileBuf + pDos->e_lfanew; PIMAGE_NT_HEADERS32 pNT = (PIMAGE_NT_HEADERS32)stPEHeadAddr; //区段数 DWORD dwSectionCount = pNT->FileHeader.NumberOfSections; //内存对齐大小 DWORD dwMemoruAil = pNT->OptionalHeader.SectionAlignment; PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT); //距离命中节的起始虚拟地址的偏移值。 DWORD dwDiffer = 0; for (DWORD i = 0; i < dwSectionCount; i++) { //模拟内存对齐机制 DWORD dwBlockCount = pSection[i].SizeOfRawData / dwMemoruAil; dwBlockCount += pSection[i].SizeOfRawData%dwMemoruAil ? 1 : 0; DWORD dwBeginVA = pSection[i].VirtualAddress; DWORD dwEndVA = pSection[i].VirtualAddress + dwBlockCount * dwMemoruAil; //如果stRVA在某个区段中 if (stRVA >= dwBeginVA && stRVA < dwEndVA) { dwDiffer = stRVA - dwBeginVA; return pSection[i].PointerToRawData + dwDiffer; } else if (stRVA < dwBeginVA)//在文件头中直接返回 { return stRVA; } } return 0; }
/************************************************************************/ /* 功能:文件偏移地址和虚拟地址的转换 参数:stOffset:文件偏移地址 lpFileBuf:虚拟内存起始地址 返回:转换后的虚拟地址 */ /************************************************************************/ size_t Offset2VA(size_t stOffset, PVOID lpFileBuf) { //获取DOS头 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuf; //获取PE头 //e_lfanew:PE头相对于文件的偏移地址 size_t stPEHeadAddr = (size_t)lpFileBuf + pDos->e_lfanew; PIMAGE_NT_HEADERS32 pNT = (PIMAGE_NT_HEADERS32)stPEHeadAddr; //区段数 DWORD dwSectionCount = pNT->FileHeader.NumberOfSections; //映像地址 DWORD dwImageBase = pNT->OptionalHeader.ImageBase; //区段头 PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT); //相对大小 DWORD dwDiffer = 0; for (DWORD i = 0; i < dwSectionCount; i++) { //区段的起始地址和结束地址 DWORD dwBeginVA = pSection[i].PointerToRawData; DWORD dwEndVA = pSection[i].PointerToRawData + pSection[i].SizeOfRawData; //如果文件偏移地址在dwBeginVA和dwEndVA之间 if (stOffset >= dwBeginVA && stOffset < dwEndVA) { //相对大小 dwDiffer = stOffset - dwBeginVA; //进程的起始地址 + 区段的相对地址 + 相对区段的大小 return dwImageBase + pSection[i].VirtualAddress + dwDiffer; } else if (stOffset < dwBeginVA) //如果文件偏移地址不在区段中 { return dwImageBase + stOffset; } } return 0; }