pe结构学心得(六)--获取重定位表
// PERelocationTable.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <time.h>
#include <imagehlp.h>
#pragma comment (lib, "imagehlp.lib")
int _tmain(int argc, _TCHAR* argv[])
{
while (TRUE) {
WCHAR cFile[256] = {0};
printf("Please enter the file name and path:");
wscanf(L"%s",cFile);
HANDLE hFile = NULL;
hFile = ::CreateFile((LPCWSTR)cFile,GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL);
if (hFile == INVALID_HANDLE_VALUE){
printf("Create file failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//创建文件映射
HANDLE hMap = NULL;
hMap = ::CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,0);
if (!hMap){
printf("Create file mapping failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//映射要自己进程的空间
LPVOID pMap = NULL;
pMap = ::MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
if (!pMap){
printf("Mapping file failed (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//后面计算文件偏移的时候要用到的
ULONG dwImageBase = (ULONG)pMap;
//获得DOS头文件指针
PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头文件
pDosHeader = (PIMAGE_DOS_HEADER)pMap;
//判断DOS头标志 IMAGE_DOS_SIGNATURE 0x5A4D MZ
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){
printf("Not DOS Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//获得PE头文件指针
PIMAGE_NT_HEADERS pPeHeaders = NULL;//PE头文件
pPeHeaders = (PIMAGE_NT_HEADERS)((LONG)pMap + pDosHeader->e_lfanew);
//判断PE头标志 IMAGE_NT_SIGNATURE 0x00004550 PE00
if (pPeHeaders->Signature != IMAGE_NT_SIGNATURE){
printf("Not PE Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//重定位信息 - dwImageBase
PIMAGE_BASE_RELOCATION pRelocation = (PIMAGE_BASE_RELOCATION)::ImageRvaToVa(pPeHeaders, pMap, pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, NULL);
int i = 0;
DWORD dwSize = 0; //用来累计每个块的大小,当块的累计大小和pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size相等时说明块已经到了末尾
PWORD pTypeOffset = NULL; //TypeOffset的指针
do {
dwSize += (DWORD)pRelocation->SizeOfBlock;
printf("%d.Relocation Block:\n", ++i);
printf("---------------------------------------------------------------------------\n");
printf("\tVirtualAddress:\t0x%08x\tOffset:0x%08x\n\tSizeOfBlock:\t0x%08x\n\n",
(pRelocation->VirtualAddress), //
(ULONG)(&(pRelocation->VirtualAddress)) - dwImageBase, //VirtualAddress在文件中的偏移量,也就是VA值存放在文件中的那个位置
pRelocation->SizeOfBlock);
printf("\tType\t\t\t\tRVA\t\tOffset\n");
printf("\t-------------------------------------------------------------------\n");
pTypeOffset = (PWORD)pRelocation + (sizeof(pRelocation->VirtualAddress) + sizeof(pRelocation->SizeOfBlock))/sizeof(WORD); //其实就是4
for (UINT j = 0; j < (UINT)((pRelocation->SizeOfBlock - sizeof(pRelocation->VirtualAddress) - sizeof(pRelocation->SizeOfBlock))/sizeof(WORD));j++) {
switch ((*pTypeOffset & 0xf000) >> 12) { //右移12位
case 0:
printf("\t(%d)IMAGE_REL_BASED_ABSOLUTE\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 1:
printf("\t(%d)IMAGE_REL_BASED_HIGH\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 2:
printf("\t(%d)IMAGE_REL_BASED_LOW\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 3:
printf("\t(%d)IMAGE_REL_BASED_HIGHLOW\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 4:
printf("\t(%d)IMAGE_REL_BASED_HIGHADJ\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 5:
printf("\t(%d)IMAGE_REL_BASED_MIPS_JMPADDR\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
case 9:
printf("\t(%d)IMAGE_REL_BASED_MIPS_JMPADDR16\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
//printf("\tIMAGE_REL_BASED_IA64_IMM64\t%d\t\t0x%x\n", (*pTypeOffset & 0xf000) >> 12, (ULONG)((*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress)));
break;
case 10:
printf("\t(%d)IMAGE_REL_BASED_DIR64\t0x%08x\t0x%08x\n",
(*pTypeOffset & 0xf000) >> 12,
(*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress),
(ULONG)::ImageRvaToVa(pPeHeaders, pMap, (*pTypeOffset & 0x0fff) + (pRelocation->VirtualAddress), NULL) - dwImageBase);
break;
default:
break;
}
pTypeOffset++;
}
printf("\n");
pRelocation = (PIMAGE_BASE_RELOCATION)((ULONG)pRelocation + (ULONG)pRelocation->SizeOfBlock); //一定要强制转换为无符号数进行运算,然后再强制转换为指针
} while ((DWORD)pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != dwSize); //根据块的总大小判断是否结束
//关闭打开的句柄,释放资源
::UnmapViewOfFile(pMap);
::CloseHandle(hMap);
::CloseHandle(hFile);
}
system("pause");
return 0;
}
