static bool PerformBaseRelocation(ref IMAGE_NT_HEADERS OrgNTHeaders, IntPtr pCode, IntPtr delta) { if (OrgNTHeaders.OptionalHeader.BaseRelocationTable.Size == 0) { return(delta == IntPtr.Zero); } for (IntPtr pRelocation = PtrAdd(pCode, OrgNTHeaders.OptionalHeader.BaseRelocationTable.VirtualAddress);;) { IMAGE_BASE_RELOCATION Relocation = PtrRead <IMAGE_BASE_RELOCATION>(pRelocation); if (Relocation.VirtualAdress == 0) { break; } IntPtr pDest = PtrAdd(pCode, Relocation.VirtualAdress); IntPtr pRelInfo = PtrAdd(pRelocation, Sz.IMAGE_BASE_RELOCATION); uint RelCount = ((Relocation.SizeOfBlock - Sz.IMAGE_BASE_RELOCATION) / 2); for (uint i = 0; i != RelCount; i++, pRelInfo = PtrAdd(pRelInfo, sizeof(ushort))) { ushort relInfo = (ushort)Marshal.PtrToStructure(pRelInfo, typeof(ushort)); BasedRelocationType type = (BasedRelocationType)(relInfo >> 12); // the upper 4 bits define the type of relocation int offset = (relInfo & 0xfff); // the lower 12 bits define the offset IntPtr pPatchAddr = PtrAdd(pDest, offset); switch (type) { case BasedRelocationType.IMAGE_REL_BASED_ABSOLUTE: // skip relocation break; case BasedRelocationType.IMAGE_REL_BASED_HIGHLOW: // change complete 32 bit address int patchAddrHL = (int)Marshal.PtrToStructure(pPatchAddr, typeof(int)); patchAddrHL += (int)delta; Marshal.StructureToPtr(patchAddrHL, pPatchAddr, false); break; case BasedRelocationType.IMAGE_REL_BASED_DIR64: long patchAddr64 = (long)Marshal.PtrToStructure(pPatchAddr, typeof(long)); patchAddr64 += (long)delta; Marshal.StructureToPtr(patchAddr64, pPatchAddr, false); break; } } // advance to next relocation block pRelocation = PtrAdd(pRelocation, Relocation.SizeOfBlock); } return(true); }
private bool PerformBaseRelocation(PtrDiffT delta) { int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.BaseRelocationTable; if (directory->Size == 0) { return(delta == 0); } if (directory->Size > 0) { IMAGE_BASE_RELOCATION *relocation = (IMAGE_BASE_RELOCATION *)(_codeBase + directory->VirtualAddress); while (relocation->VirtualAdress > 0) { byte * dest = _codeBase + relocation->VirtualAdress; ushort *relInfo = (ushort *)((byte *)relocation + imageSizeOfBaseRelocation); for (int i = 0; i < ((relocation->SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++, relInfo++) { // the upper 4 bits define the type of relocation BasedRelocationType type = (BasedRelocationType)(*relInfo >> 12); // the lower 12 bits define the offset int offset = *relInfo & 0xfff; switch (type) { case BasedRelocationType.IMAGE_REL_BASED_ABSOLUTE: break; case BasedRelocationType.IMAGE_REL_BASED_HIGHLOW: uint *patchAddrHL = (uint *)(dest + offset); * patchAddrHL += (uint)delta; break; case BasedRelocationType.IMAGE_REL_BASED_DIR64: ulong *patchAddr64 = (ulong *)(dest + offset); * patchAddr64 += (ulong)delta; break; default: break; } } // advance to next relocation block relocation = (IMAGE_BASE_RELOCATION *)(((byte *)relocation) + relocation->SizeOfBlock); } } return(true); }