Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)
生活随笔
收集整理的这篇文章主要介绍了
Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
RVA-FOA之间转换
1.首先PE头加载到内存之后是和文件头内容一样的,就算是偏移不同,一个是磁盘扇区大小(400H)另一个是内存页大小(1000H),但是因为两个都是开头位置,所以相同。
2.看下IMAGE_SECTION_HEADER定义
也就是这样:
然后就可以算了(RVA->FOA)
(1) RVA20 < RVA < RVA30 可以知道在第二节
(2) 然后 off = RVA - RVA20 ,得出距离第二节的偏移off
(3) FOA = FOA 20 + off 求出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; return pSection[i].VirtualAddress + dwDiffer;} else if (stOffset < dwBeginVA) //如果文件偏移地址不在区段中 { return dwImageBase + stOffset; } } return 0; }
测试了上面两个函数,没发现什么问题,测试结果:
随手写了个简单的工具,直接控制台写的,功能简单,懒得写界面了。源码在:
http://download.csdn.net/detail/u013761036/9643230
运行效果:
总结
以上是生活随笔为你收集整理的Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Windows Pe 第三章 PE头文件
- 下一篇: Windows核心编程 第八章 用户方式