windows PE文件格式笔记(二)RVAToFOV

什么是RVA,FOV

RVA是相对虚拟地址,FOV是文件偏移

由于PE文件在磁盘上和在内存中的对齐粒度不同,会导致同一个PE文件在磁盘上和在内存中有两个不同的偏移,即,FOV和RVA.

在PE格式中查看对齐粒度

PE文件在磁盘和在内存的对齐粒度分别为: FileAlignment 和SectionAlignment

他们在PE扩展头中可以找到,PE扩展头的结构体:

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment; //内存对齐粒度
    DWORD   FileAlignment; //文件对齐粒度
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

FileAlignment一般是磁盘一个物理扇区的大小,512字节,即:0x200;

SectionAlignment的大小一般为0x1000,也就是win32中一个页的大小(4KB);

这两个值由链接器填写,SectionAlignment必须大于等于FileAlignment,在高版本的链接器中,SectionAlignment可能与FileAlignment相等,就无需进行RVA和FOV的转换了。

RVA转FOV

在解析PE文件时,经常会用到RAV与FOV的转换,

在RVA转FOV有以下几个步骤:

1.判断指定RVA落在哪个节区内。

2.获取该节区在内存中的虚拟地址,即:IMAGE_SECTION_HEADER.VirtualAddress

3.求出offset=指定RVA-IMAGE_SECTION_HEADER.VirtualAddress

4.得到FOV=offset+IMAGE_SECTION_HEADER.PointerToRaw(在文件中的起始地址)

可以通过IMAGE_FILE_HEADER+SizeOfOptionalHeader得到IMAGE_SECTION_HEADER地址,在IMAGE_FILE_HEADER得到NumberOfSections

具体转换代码:

ULONG RVAToFOV(PIMAGE_SECTION_HEADER pSectionHeader, ULONG NumberOfSections, ULONG RVA)
{
	for (int i = 0; i < NumberOfSections; i++)
	{
		if (pSectionHeader->VirtualAddress <= RVA && RVA <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
		{
			return RVA - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
		}
		pSectionHeader++;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值