RVA 转 RAW

直接上源码:

#include<stdio.h>
#include<Windows.h>
int main()
{
	LPCSTR lpFileName="D:\\PyCharm Community Edition 2019.2.4\\bin\\IdeaWin32.dll";
	HANDLE hFile;
	hFile=CreateFileA(lpFileName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
	if(hFile==INVALID_HANDLE_VALUE)
	{
		MessageBoxA(0,"文件打开失败",0,MB_OK);
		return 0;
	}
	DWORD FileSize=GetFileSize(hFile,0);
	BYTE* lpBuffer=new BYTE[FileSize];
	ReadFile(hFile,lpBuffer,FileSize,0,0);
	/*定义DOS头*/
	PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)lpBuffer;
	/*定义NT头*/
	PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew+lpBuffer);
	/*定义可选头*/
	PIMAGE_OPTIONAL_HEADER pOptionalHeader=&(pNtHeader->OptionalHeader);
	/*定义文件头*/
	PIMAGE_FILE_HEADER pFileHeader=&(pNtHeader->FileHeader);
	/*获取节表的数量*/
	DWORD SectionNumber=pFileHeader->NumberOfSections;
	/*获取节的位置,方法,从NT头加上整个NT头的大小*/
	PIMAGE_SECTION_HEADER SectionHeader=(PIMAGE_SECTION_HEADER)(pNtHeader+0x18+pFileHeader->SizeOfOptionalHeader);
	/*定位到数据目录表(通过这种方式获取到的是数据目录表的第一个元素也就是导出表),但是通过IMAGE_EXPORT_DIRECTORY* Export=(IMAGE_EXPORT_DIRECTORY*)((BYTE *)pNtHeader+0x78)这种方式得到的是导出表的结构*/
	PIMAGE_DATA_DIRECTORY pDirectory=(PIMAGE_DATA_DIRECTORY)(pOptionalHeader->DataDirectory);
	/*获取导出表的虚拟地址*/
	DWORD ExportRVA=pDirectory->VirtualAddress;//注意这个地址是一个RVA,是数据块的起始RVA
	/*开始进行转换,RVA->RAW 过程中用到的两个参数:第一个(导出表虚拟地址:ExportRVA)第二个(基址:pDosHeader)*/
	/*转换的思路:1、获取节区表的开始的虚拟地址
	2、获取节区表的结束地址
	3、判断要转换的RVA所在节区
	4、利用公式进行计算转换  RAW=RVA-VA+PointToRAW*/
	for(int i=0;i<SectionNumber;i++)
	{
		/*计算当前节区的开始地址*/
		DWORD SectionBegin=SectionHeader[i].VirtualAddress;//区块的RVA地址
		/*计算当前节区的结束地址*/
		DWORD SectionEnd=SectionHeader[i].VirtualAddress+SectionHeader[i].SizeOfRawData;//(这里的大小在实际使用中是区块的起始RVA+区块的大小,但是在实际使用中要考虑到文件的对齐)
		/*判断要求的RVA是否在当前的节区内*/
		if(ExportRVA>SectionBegin&&ExportRVA<SectionEnd)
		{
			/*如果在当前的节区内*/
			DWORD ExportRAW=ExportRVA-SectionBegin+SectionHeader[i].PointerToRawData;
			printf("转换结果:%x",ExportRAW);
		}
	}
}

关于地址转换的题外话:
用CreateFile获取到文件的句柄,之后用ReadFile将文件读取到缓冲区里边,这时候缓冲区里边存储的文件是源文件在磁盘上的格式,并没有按照相应的对齐粒度展开,在遍历导出表的时候,获取的是导出表的RVA和VA(这两个地址都是文件在内存中的地址,也就是按照内存中的对齐粒度对齐之后的地址),如果想要根据获取到的导出表的RVA和VA获取导出表的函数,要将地址进行转换,转换为RAW,也就是文件偏移,之后再到缓冲区里边根据地址进行遍历(因为用ReadFile将文件读取到内存中的时候,文件保持再磁盘上的对齐状态)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值