打印重定位表

    科技2024-08-09  28

    文章目录

    一、流程二、流程三、完整代码

    一、流程

    1、File-> FileBuffer 2、获取头信息 3、获取结构体数组的信息 4、获取导出表的地址RVA和FOA 5、获取导出表在文件中的地址 6、循环重定位表 7、获取数据块的FOA 8、判断数据块在那个节中 9、获取要修改数据的个数和位置 10、循环要修改的数据并判断是否要修改 11、指向下一个数据块

    二、流程

    1、File-> FileBuffer 2、获取头信息 3、获取结构体数组的信息

    //指向数组 PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionHeader->DataDirectory;

    4、获取导出表的地址RVA和FOA

    //重定位表的地址Rva DWORD dwRelocationTableRva = pDataDirectory[5].VirtualAddress; //重定位表的地址Foa DWORD dwRelocationTableFoa = RvaToFoa(pFileBuffer,dwRelocationTableRva);

    5、获取导出表在文件中的地址

    //重定位表在文件中的地址 PIMAGE_BASE_RELOCATION pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + dwRelocationTableFoa);

    6、循环重定位表

    //循环重定位表 for(int i=1 ; pRelocationTable->SizeOfBlock && pRelocationTable->VirtualAddress ; i++) { }

    7、获取数据块的FOA

    //重定位表中数据的Foa DWORD Foa = RvaToFoa(pFileBuffer,pRelocationTable->VirtualAddress);

    8、判断数据块在那个节中

    //循环判断数据在哪个节中 for(int t=0 ; pNTHeader->FileHeader.NumberOfSections ; t++) { //节的起始和结束位置 DWORD Begin = RvaToFoa(pFileBuffer,pSectionHeader[t].VirtualAddress); DWORD End = RvaToFoa(pFileBuffer,pSectionHeader[t].VirtualAddress) + pSectionHeader[t].Misc.VirtualSize; //判断 if(Foa >= Begin && Foa <= End) { memcpy(SecName,pSectionHeader[t].Name,8); break; } } printf("-------------------------------------%s-------------------------------------\n",SecName);

    9、获取要修改数据的个数和位置

    //要修改的数据个数 DWORD Size = (pRelocationTable->SizeOfBlock - 0x8)/2; //要修改数据的起始位置 PWORD RecAddr = (PWORD)((PBYTE)pRelocationTable + 8);

    10、循环要修改的数据并判断是否要修改

    //循环要修改的数据 for(DWORD j=0 ; j < Size ; j++) { //要修改数据的真实地址 DWORD Offset = (RecAddr[j] & 0X0FFF) + Foa; //判断是否需要修改0是不需要修改,3是需要修改 WORD Type = RecAddr[j] >> 12; if(Type == 0) { printf("\t\t[%d]\t[---------------]\tABSOLUTE[%d]\n",j+1,Type); continue; } //打印数据真实地址和类型 printf("\t\t[%d]\t[%08X]\tHIGHLOW[%d]\n",j+1,Offset,Type); }

    11、指向下一个数据块

    //重置节名 memset(SecName,0,9); //指向下一个数据块 pRelocationTable = (PIMAGE_BASE_RELOCATION)((PBYTE)pRelocationTable + pRelocationTable->SizeOfBlock);

    三、完整代码

    #include "stdafx.h" #include <windows.h> #include "stdlib.h" #define FILEPATH_IN "C:/testdll.dll" DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer ) { FILE *pFile = NULL; DWORD fileSize = 0; //文件大小 LPVOID pTempFileBuffer = NULL; //缓冲区首地址 pFile = fopen(lpszFile,"rb"); //打开文件 if(!pFile) { printf("打开文件失败"); return NULL; } //读取文件大小 fseek(pFile,0,SEEK_END); //将指针从开始的位置移动到末尾 fileSize = ftell(pFile); //获取数据大小 //分配缓冲区(申请内存) pTempFileBuffer = malloc(fileSize); if(!pTempFileBuffer) { printf("分配空间失败"); fclose(pFile); return NULL; } //将文件数据读取到缓冲区 fseek(pFile,0,SEEK_SET); //将指针指向开始 size_t n = fread(pTempFileBuffer,fileSize,1,pFile); //将数据读取到缓冲区中 if(!n) { printf("读取数据失败"); free(pTempFileBuffer); //释放内存 fclose(pFile); //关闭文件 return NULL; } //关闭文件 *pFileBuffer = pTempFileBuffer; pTempFileBuffer = NULL; fclose(pFile); //关闭文件 return fileSize; } //********************************************************************** DWORD RvaToFoa(IN LPVOID pFileBuffer, IN DWORD dwRva) { PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; //DOS头 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; //NT头地址 pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew); //标准PE头地址 pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4); //可选PE头地址 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER); //第一个节表地址 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader); for(int i=0 ; i < pPEHeader->NumberOfSections ; i++) { //节在内存中的位置RVA DWORD dwSectionBeginRva = pSectionHeader[i].VirtualAddress; //节在内存中相对于文件中结束的位置RVA DWORD dwSectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData; //判断RVA是否在当前节中 if(dwRva >= dwSectionBeginRva && dwRva <= dwSectionEndRva) { //FOA = RVA - 节在内存中的位置 + 节在文件中的偏移 DWORD dwFoa = dwRva - dwSectionBeginRva + pSectionHeader[i].PointerToRawData; return dwFoa; } } } //********************************************************************** VOID TestPrintRelocation() { LPVOID pFileBuffer = NULL; PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; //File-> FileBuffer DWORD Size = ReadPEFile(FILEPATH_IN,&pFileBuffer); //调用函数读取文件数据 if(!pFileBuffer || !Size) { printf("File-> FileBuffer失败"); return; } BYTE SecName[9] = {0}; //获取头信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuffer + pDosHeader->e_lfanew + 0x4 + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pNTHeader->FileHeader.SizeOfOptionalHeader); //指向数组 PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionHeader->DataDirectory; //重定位表的地址Rva DWORD dwRelocationTableRva = pDataDirectory[5].VirtualAddress; //重定位表的地址Foa DWORD dwRelocationTableFoa = RvaToFoa(pFileBuffer,dwRelocationTableRva); //重定位表在文件中的地址 PIMAGE_BASE_RELOCATION pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + dwRelocationTableFoa); //循环重定位表 for(int i=1 ; pRelocationTable->SizeOfBlock && pRelocationTable->VirtualAddress ; i++) { //重定位表中数据的Foa DWORD Foa = RvaToFoa(pFileBuffer,pRelocationTable->VirtualAddress); //循环判断数据在哪个节中 for(int t=0 ; pNTHeader->FileHeader.NumberOfSections ; t++) { //节的起始和结束位置 DWORD Begin = RvaToFoa(pFileBuffer,pSectionHeader[t].VirtualAddress); DWORD End = RvaToFoa(pFileBuffer,pSectionHeader[t].VirtualAddress) + pSectionHeader[t].Misc.VirtualSize; //判断 if(Foa >= Begin && Foa <= End) { memcpy(SecName,pSectionHeader[t].Name,8); break; } } printf("-------------------------------------%s-------------------------------------\n",SecName); //要修改的数据个数 DWORD Size = (pRelocationTable->SizeOfBlock - 0x8)/2; //要修改数据的起始位置 PWORD RecAddr = (PWORD)((PBYTE)pRelocationTable + 8); printf("\t\tIndex\tFoa\t\ttype\t[BLOCK Items]\n"); //循环要修改的数据 for(DWORD j=0 ; j < Size ; j++) { //要修改数据的真实地址 DWORD Offset = (RecAddr[j] & 0X0FFF) + Foa; //判断是否需要修改0是不需要修改,3是需要修改 WORD Type = RecAddr[j] >> 12; if(Type == 0) { printf("\t\t[%d]\t[---------------]\tABSOLUTE[%d]\n",j+1,Type); continue; } //打印数据真实地址和类型 printf("\t\t[%d]\t[%08X]\tHIGHLOW[%d]\n",j+1,Offset,Type); } //重置节名 memset(SecName,0,9); //指向下一个数据块 pRelocationTable = (PIMAGE_BASE_RELOCATION)((PBYTE)pRelocationTable + pRelocationTable->SizeOfBlock); } } //********************************************************************** int main(int argc, char* argv[]) { TestPrintRelocation(); getchar(); return 0; }
    Processed: 0.011, SQL: 8