Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)
2016-10-07 20:53
323 查看
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
运行效果:
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-相关编程-1(PE头内容获取)
- PE文件的相对虚拟地址(RVA)和文件偏移地址(FOA)的转换
- 【PE结构】由浅入深PE基础学习-菜鸟手动查询导出表、相对虚拟地址(RVA)与文件偏移地址转换(FOA)
- PE文件结构(二) 区块,文件偏移与RVA转换
- Windows Pe 第三章 PE头文件(中)
- PE文件中, RVA和文件偏移的转换
- PE文件中RVA和Offset的转换
- [PE文件结构学习]1.相对虚拟地址(RVA)与物理地址的转换
- [PE结构分析] 7.相对虚拟地址(RVA)和文件偏移间的转换
- 流水账笔记:PE文件格式(RVA & FOA)
- Windows Pe 第三章 PE头文件(下)
- PE文件RV转FOA及FOA转RVA
- 理解PE文件相对虚拟地址(RVA)到文件偏移的转换
- :PE文件中RVA和RAW是如何互相转换的?"(看雪)
- Windows文件系统驱动程序编程相关链接
- 我自己的PE文件RVA-VA-Offset心得
- 文件系统的相关编程(下)
- Security证书相关文件格式汇总及其格式转换工具介绍
- PE文件关于虚拟相对地址RVA与基于文件的偏移地址关系
- Windows & Unix 文件格式之迷, 空格、回车换行、tab 转换及其相关工具(转载)