建设网站类型,wordpress竖版图片尺寸,遵义本地网站,国外浏览器入口在可执行文件PE文件结构中#xff0c;通常我们需要用到地址转换相关知识#xff0c;PE文件针对地址的规范有三种#xff0c;其中就包括了VA#xff0c;RVA#xff0c;FOA三种#xff0c;这三种该地址之间的灵活转换也是非常有用的#xff0c;本节将介绍这些地址范围如何…在可执行文件PE文件结构中通常我们需要用到地址转换相关知识PE文件针对地址的规范有三种其中就包括了VARVAFOA三种这三种该地址之间的灵活转换也是非常有用的本节将介绍这些地址范围如何通过编程的方式实现转换。
如下是三种格式的异同点
VAVirtual Address虚拟地址它是在进程的虚拟地址空间中的地址用于在运行时访问内存中的数据和代码。VA是相对于进程基址的偏移量。在不同的进程中相同的VA可能映射到不同的物理地址。RVARelative Virtual Address相对虚拟地址它是相对于模块基址Module Base Address的偏移量用于定位模块内部的数据和代码。RVA是相对于模块基址的偏移量通过将模块基址和RVA相加可以计算出相应的VA。FOAFile Offset Address文件偏移地址它是相对于文件起始位置的偏移量用于定位可执行文件中的数据和代码在文件中的位置。通过将文件偏移地址和节表中的指定节的起始位置相加可以计算出相应的FOA。
VA虚拟地址转换为FOA文件偏移
VA地址代指的是程序加载到内存后的内存地址而FOA地址则代表文件内的物理地址通过编写VA_To_FOA则可实现将一个虚拟地址转换为文件偏移地址该函数的实现方式首先得到ImageBase镜像基地址并得到NumberOfSections节数量有了该数量以后直接循环通过判断语句将节限定在一个区间内该区间dwVA Section_Start dwVA Section_Ends当找到后首先通过VA-ImageBase得到当前的RVA地址接着通过该地址减去VirtualAddress并加上PointerToRawData文件指针即可获取到文件内的偏移。
#include iostream
#include Windows.h
#include ImageHlp.h#pragma comment(lib,Imagehlp.lib)// 读取NT头
PIMAGE_NT_HEADERS GetNtHeader(PVOID ImageBase)
{PIMAGE_DOS_HEADER pDosHeader (PIMAGE_DOS_HEADER)ImageBase;if (pDosHeader-e_magic ! IMAGE_DOS_SIGNATURE){return NULL;}PIMAGE_NT_HEADERS pNtHeaders (PIMAGE_NT_HEADERS)((BYTE*)ImageBase pDosHeader-e_lfanew);if (pNtHeaders-Signature ! IMAGE_NT_SIGNATURE){return NULL;}return pNtHeaders;
}// 读取PE结构的封装
HANDLE OpenPeFile(LPTSTR FileName)
{HANDLE hFile, hMapFile, lpMapAddress NULL;DWORD dwFileSize 0;// CreateFile 既可以创建文件也可以打开文件这里则是打开文件的含义hFile CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile INVALID_HANDLE_VALUE){return 0;}// 获取到文件大小dwFileSize GetFileSize(hFile, NULL);// 创建文件的内存映像hMapFile CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);if (hMapFile NULL){return 0;}// 读取映射中的内存并返回一个句柄lpMapAddress MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);if (lpMapAddress ! NULL){return lpMapAddress;}return 0;
}// 将 VA(虚拟地址) -- 转换为 FOA(文件偏移)
DWORD VA_To_FOA(HANDLE ImageBase, DWORD dwVA)
{PIMAGE_NT_HEADERS pNtHead NULL;PIMAGE_FILE_HEADER pFileHead NULL;PIMAGE_SECTION_HEADER pSection NULL;DWORD NumberOfSectinsCount 0;DWORD dwImageBase 0;pNtHead GetNtHeader(ImageBase);pSection IMAGE_FIRST_SECTION(pNtHead);dwImageBase pNtHead-OptionalHeader.ImageBase;NumberOfSectinsCount pNtHead-FileHeader.NumberOfSections;for (int each 0; each NumberOfSectinsCount; each){// 获取节的开始地址与结束地址DWORD Section_Start dwImageBase pSection[each].VirtualAddress;DWORD Section_Ends dwImageBase pSection[each].VirtualAddress pSection[each].Misc.VirtualSize;// 判断当前的VA地址落在了那个节上if (dwVA Section_Start dwVA Section_Ends){DWORD RVA dwVA - pNtHead-OptionalHeader.ImageBase; // 计算RVADWORD FOA pSection[each].PointerToRawData (RVA - pSection[each].VirtualAddress); // 计算FOAreturn FOA;}}return -1;
}int main(int argc, char * argv[])
{HANDLE lpMapAddress NULL;// 打开PE文件lpMapAddress OpenPeFile(Ld://lyshark.exe);// 转换DWORD FOA VA_To_FOA(lpMapAddress, 0x401000);printf(VA -- FOA 结果为: %x \n, FOA);system(pause);return 0;
}上述代码运行后即可获取到内存地址0x401000对应的文件地址为0x1000读者可自行打开WinHex验证是否相等如下图所示 RVA相对地址转换为FOA文件偏移
所谓的相对地址则是内存地址减去基址所获得的地址该地址的计算同样可以使用代码实现如下RVA_To_FOA函数可用于将一个相对地址转换为文件偏移如果内存VA地址是0x401000而基址是0x400000那么相对地址就是0x1000将相对地址转换为FOA文件偏移首相要将相对地址加上基址我们通过相对地址减去PointerToRawData数据指针即可获取到文件偏移。
#include iostream
#include Windows.h
#include ImageHlp.h#pragma comment(lib,Imagehlp.lib)// 读取NT头
PIMAGE_NT_HEADERS GetNtHeader(PVOID ImageBase)
{PIMAGE_DOS_HEADER pDosHeader (PIMAGE_DOS_HEADER)ImageBase;if (pDosHeader-e_magic ! IMAGE_DOS_SIGNATURE){return NULL;}PIMAGE_NT_HEADERS pNtHeaders (PIMAGE_NT_HEADERS)((BYTE*)ImageBase pDosHeader-e_lfanew);if (pNtHeaders-Signature ! IMAGE_NT_SIGNATURE){return NULL;}return pNtHeaders;
}// 读取PE结构的封装
HANDLE OpenPeFile(LPTSTR FileName)
{HANDLE hFile, hMapFile, lpMapAddress NULL;DWORD dwFileSize 0;// CreateFile 既可以创建文件也可以打开文件这里则是打开文件的含义hFile CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile INVALID_HANDLE_VALUE){return 0;}// 获取到文件大小dwFileSize GetFileSize(hFile, NULL);// 创建文件的内存映像hMapFile CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);if (hMapFile NULL){return 0;}// 读取映射中的内存并返回一个句柄lpMapAddress MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);if (lpMapAddress ! NULL){return lpMapAddress;}return 0;
}// 将 RVA(虚拟地址) -- 转换为 FOA(文件偏移)
DWORD RVA_To_FOA(HANDLE ImageBase, DWORD dwRVA)
{PIMAGE_NT_HEADERS pNtHead NULL;PIMAGE_FILE_HEADER pFileHead NULL;PIMAGE_SECTION_HEADER pSection NULL;DWORD NumberOfSectinsCount 0;DWORD dwImageBase 0;pNtHead GetNtHeader(ImageBase);pSection IMAGE_FIRST_SECTION(pNtHead);dwImageBase pNtHead-OptionalHeader.ImageBase;NumberOfSectinsCount pNtHead-FileHeader.NumberOfSections;for (int each 0; each NumberOfSectinsCount; each){DWORD Section_Start pSection[each].VirtualAddress; // 计算RVA开始位置DWORD Section_Ends pSection[each].VirtualAddress pSection[each].Misc.VirtualSize; // 计算RVA结束位置if (dwRVA Section_Start dwRVA Section_Ends){DWORD VA pNtHead-OptionalHeader.ImageBase dwRVA; // 得到VA地址DWORD FOA pSection[each].PointerToRawData (dwRVA - pSection[each].VirtualAddress); // 得到FOAreturn FOA;}}return -1;
}int main(int argc, char * argv[])
{// 打开文件HANDLE lpMapAddress NULL;lpMapAddress OpenPeFile(Ld://lyshark.exe);// 计算地址DWORD FOA RVA_To_FOA(lpMapAddress, 0x1000);printf(RVA -- FOA 结果为: %x \n, FOA);system(pause);return 0;
}我们还是以上述功能为例计算相对地址0x1000的文件偏移则可以得到0x1000的文件偏移值如下图所示 FOA文件偏移转换为VA虚拟地址
将文件内的偏移地址FOA转换为内存虚拟地址在转换时首先通过VirtualAddress节虚拟地址加上文件偏移地址减去PointerToRawData数据域指针得到相对地址再次加上ImageBase基地址即可获取到实际虚拟地址。
#include iostream
#include Windows.h
#include ImageHlp.h#pragma comment(lib,Imagehlp.lib)// 读取NT头
PIMAGE_NT_HEADERS GetNtHeader(PVOID ImageBase)
{PIMAGE_DOS_HEADER pDosHeader (PIMAGE_DOS_HEADER)ImageBase;if (pDosHeader-e_magic ! IMAGE_DOS_SIGNATURE){return NULL;}PIMAGE_NT_HEADERS pNtHeaders (PIMAGE_NT_HEADERS)((BYTE*)ImageBase pDosHeader-e_lfanew);if (pNtHeaders-Signature ! IMAGE_NT_SIGNATURE){return NULL;}return pNtHeaders;
}// 读取PE结构的封装
HANDLE OpenPeFile(LPTSTR FileName)
{HANDLE hFile, hMapFile, lpMapAddress NULL;DWORD dwFileSize 0;// CreateFile 既可以创建文件也可以打开文件这里则是打开文件的含义hFile CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile INVALID_HANDLE_VALUE){return 0;}// 获取到文件大小dwFileSize GetFileSize(hFile, NULL);// 创建文件的内存映像hMapFile CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);if (hMapFile NULL){return 0;}// 读取映射中的内存并返回一个句柄lpMapAddress MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);if (lpMapAddress ! NULL){return lpMapAddress;}return 0;
}// 将 FOA(文件偏移) -- 转换为 VA(虚拟地址)
DWORD FOA_To_VA(HANDLE ImageBase, DWORD dwFOA)
{PIMAGE_NT_HEADERS pNtHead NULL;PIMAGE_FILE_HEADER pFileHead NULL;PIMAGE_SECTION_HEADER pSection NULL;DWORD NumberOfSectinsCount 0;DWORD dwImageBase 0;pNtHead GetNtHeader(ImageBase);pSection IMAGE_FIRST_SECTION(pNtHead);dwImageBase pNtHead-OptionalHeader.ImageBase;NumberOfSectinsCount pNtHead-FileHeader.NumberOfSections;for (int each 0; each NumberOfSectinsCount; each){DWORD PointerRawStart pSection[each].PointerToRawData; // 文件偏移开始位置DWORD PointerRawEnds pSection[each].PointerToRawData pSection[each].SizeOfRawData; // 文件偏移结束位置if (dwFOA PointerRawStart dwFOA PointerRawEnds){DWORD RVA pSection[each].VirtualAddress (dwFOA - pSection[each].PointerToRawData); // 计算出RVADWORD VA RVA pNtHead-OptionalHeader.ImageBase; // 计算出VAreturn VA;}}return -1;
}int main(int argc, char * argv[])
{// 打开文件HANDLE lpMapAddress NULL;lpMapAddress OpenPeFile(Ld://lyshark.exe);// 转换DWORD VA FOA_To_VA(lpMapAddress, 0x1000);printf(FOA -- VA 结果为: 0x%X \n, VA);system(pause);return 0;
}运行后即可将文件偏移0x1000转换为内存虚拟地址0x401000如下图所示 本文作者 王瑞 本文链接 https://www.lyshark.com/post/ccb722fb.html 版权声明 本博客所有文章除特别声明外均采用 BY-NC-SA 许可协议。转载请注明出处