本文主要是介绍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将文件读取到内存中的时候,文件保持再磁盘上的对齐状态)
这篇关于RVA 转 RAW的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!