PE Base Relocations如何建立起来?

时间:2013-07-02 22:09:23

标签: executable portability relocation

我目前无法理解PE Base Relocations的构建方式。

我知道可以有多个重定位,我也理解为什么以及如何完成,但我只是不能以编程方式理解它:

以下哪项是正确的(WinNT.h中的IMAGE_BASE_RELOCATION)?

// Base relocation #1
DWORD   VirtualAddress;
DWORD   SizeOfBlock; // size of current relocation
WORD    TypeOffset[1];
// Base relocation #2
DWORD   VirtualAddress;
DWORD   SizeOfBlock; // size of current relocation
WORD    TypeOffset[1];
// Base relocation #3
DWORD   VirtualAddress;
DWORD   SizeOfBlock; // size of current relocation
WORD    TypeOffset[1];

或者

DWORD   VirtualAddress;
DWORD   SizeOfBlock; // size of all relocations
WORD    TypeOffset[1]; // relocation #1
WORD    TypeOffset[1]; // relocation #2
WORD    TypeOffset[1]; // relocation #3

或两者都不正确?我该如何以编程方式遍历所有基址重定位?

目前我有这个代码,在某处似乎不正确:

DWORD baseRelocationSize = imageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
            unsigned int baseRelocationCount = baseRelocationSize / sizeof(IMAGE_BASE_RELOCATION);
            DWORD baseDelta = (DWORD_PTR)moduleBase - (DWORD_PTR)imageNtHeaders->OptionalHeader.ImageBase;

            IMAGE_BASE_RELOCATION* baseRelocation = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)moduleBase + (DWORD_PTR)imageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

            for(unsigned int i = 0; i != baseRelocationCount; ++i)
            {
                unsigned int entryCount = (baseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

                for(unsigned int j = 0; j != entryCount; ++j)
                {
                    WORD* entry = (WORD*)((DWORD_PTR)baseRelocation + (DWORD_PTR)sizeof(IMAGE_BASE_RELOCATION));
                    if((*entry >> 12) & IMAGE_REL_BASED_HIGHLOW)
                    {
                        DWORD* pdw = (PDWORD)((DWORD_PTR)moduleBase + (DWORD_PTR)baseRelocation->VirtualAddress + ((*entry) & 0xfff));
                        (*pdw) += baseDelta;
                    }

                    entry++;
                }

                baseRelocation += baseRelocation->SizeOfBlock;
            } 

2 个答案:

答案 0 :(得分:17)

您指出的选项都不完全正确/无效。

这篇关于How to inject code in a PE file的优秀教程表明,实际的IMAGE_BASE_RELOCATION结构是:

typedef struct _IMAGE_BASE_RELOCATION {
  DWORD   VirtualAddress;
  DWORD   SizeOfBlock;
} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;

document的第4.2和5.6节描述了结构。 SizeOfBlock-8实际上表示在WORD TypeOffsetVirtualAddress之后跟随了多少SizeOfBlock

我想您也会对本教程的表7感兴趣,该表显示了重定位​​表中块的结构。我将这里的表格复制粘贴以供快速参考。

enter image description here

答案 1 :(得分:4)

从某些代码.. aldo检查出反应:)

BOOL FixRelocs(void *base, void *rBase, IMAGE_NT_HEADERS *ntHd, IMAGE_BASE_RELOCATION *reloc,
               unsigned int size) {
    unsigned long ImageBase = ntHd->OptionalHeader.ImageBase;
    unsigned int nBytes = 0;
    unsigned long delta = MakeDelta(unsigned long, rBase, ImageBase);
    unsigned long *locBase;
unsigned int numRelocs;
unsigned short *locData;
unsigned int i;

while(1) {
  locBase =
     (unsigned long *)GetPtrFromRVA((DWORD)(reloc->VirtualAddress), ntHd, (PBYTE)base);
  numRelocs = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

  if(nBytes >= size) break;

  locData = MakePtr(unsigned short *, reloc, sizeof(IMAGE_BASE_RELOCATION));
  for(i = 0; i < numRelocs; i++) {       
     if(((*locData >> 12) == IMAGE_REL_BASED_HIGHLOW))
         *MakePtr(unsigned long *, locBase, (*locData & 0x0FFF)) += delta;
     locData++;
  }

  nBytes += reloc->SizeOfBlock;
  reloc = (IMAGE_BASE_RELOCATION *)locData;
   }

   return TRUE;

}