理解别人写的简单的重定位程序

看了下看雪的一篇文章,加深下对重定位的理解,其实这是一个程序

https://bbs.pediy.com/thread-76638.htm

这个程序需要用户输入的是加载基址,还有文件的路径

开始首先通过MZ头,还有e_lfanew偏移是否是PEx00x00 来判断这是否是一个PE文件

BOOL VerifyPE( PVOID pFile ) 
{ 
    PIMAGE_DOS_HEADER pDosHeader; 
    PIMAGE_NT_HEADERS pNtHeader; 
 
    pDosHeader = (PIMAGE_DOS_HEADER)pFile; 
    if ( pDosHeader->e_magic != 0x5A4D )   // compare with 'MZ' 
        return FALSE; 
 
    pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pFile + pDosHeader->e_lfanew);   // e_lfanew + 0x3c  
    if ( pNtHeader->Signature != 0x00004550 ) // compare with 'PE' 
        return FALSE; 
 
    return TRUE; 
}

重定位

计算镜像基址与真正加载基址的差值

pDosHeader = (PIMAGE_DOS_HEADER)pFile;  
pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pFile + pDosHeader->e_lfanew);   // e_lfanew + 0x3c   

dwImageBase = pNtHeader->OptionalHeader.ImageBase;  
dwDiffer = dwImageBase - BaseAddr;  // pay attention to the order 

获取重定位表RVA,并计算出File Offset

 // Get reloc table RVA  
PIMAGE_DATA_DIRECTORY pRelocTable = (PIMAGE_DATA_DIRECTORY)pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;   

// Get reloc table File Offset  
pRelocBlock = (PIMAGE_RELOCATION)( (PCHAR)pFile + RvaToFileOff( pFile, (DWORD)pRelocTable ) ); // the pRelocTable is file offset?  

之后根据重定位表循环计算真正的地址,具体如下

1、一次获取一条记录,获取其RVA,算出File Offset
2、通过与pRelocAddr相加得到储存原始地址的地方(即要修正的地址)
3、将这个要修正的地址减去之前算出来的基址的差别即可
4、最后将结果写回文件即可

pRelocAddr = pRelocBlock->VirtualAddress + (*pType & 0x0fff);     
// pRelocAddr += dwImageBase;  

// Get reloc address's File Offset  
pRelocAddr = RvaToFileOff( pFile, pRelocAddr );  

//  DWORD test = pRelocAddr;  

// Go to the Buffer offset  
pRelocAddr += (DWORD)pFile;  

// Get the reloc address  
dwRelocAddr = *(PDWORD)pRelocAddr;  

// Calculate the new address  
dwRelocAddr -= dwDiffer;  

// Copy to the file  
*(PDWORD)pRelocAddr = dwRelocAddr;
原文地址:https://www.cnblogs.com/cnsec/p/13286477.html