public void ImageBaseRelocationConstructorWorks_Test() { var ibr = new IMAGE_BASE_RELOCATION(RawStructures.RawImageBaseRelocation, 2, 12); Assert.Equal((uint)0x10000, ibr.VirtualAddress); Assert.Equal((uint)0xc, ibr.SizeOfBlock); Assert.Equal(2, ibr.TypeOffsets.Length); Assert.Equal(0x2211 >> 12, ibr.TypeOffsets[0].Type); Assert.Equal(0x2211 & 0xfff, ibr.TypeOffsets[0].Offset); Assert.Equal(0x4433 >> 12, ibr.TypeOffsets[1].Type); Assert.Equal(0x4433 & 0xfff, ibr.TypeOffsets[1].Offset); }
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); }
public void PerformBaseRelocation(UInt32 delta) { IntPtr codeBase = _module.codeBase; Int32 sizeOfBase = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_DATA_DIRECTORY directory = _module.headers.OptionalHeader.DataDirectory[5]; Int32 cnt = 0; if (directory.Size > 0) { IMAGE_BASE_RELOCATION relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, directory.VirtualAddress); while (relocation.VirtualAddress > 0) { unsafe { IntPtr dest = (IntPtr)(codeBase.ToInt32() + (int)relocation.VirtualAddress); UInt16 *relInfo = (UInt16 *)(codeBase.ToInt32() + (int)directory.VirtualAddress + sizeOfBase); UInt16 i; for (i = 0; i < ((relocation.SizeOfBlock - Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION))) / 2); i++, relInfo++) { Int32 type = *relInfo >> 12; Int32 offset = (*relInfo & 0xfff); switch (type) { case 0x00: break; case 0x03: UInt32 *patchAddrHl = (UInt32 *)((dest.ToInt32()) + (offset)); * patchAddrHl += delta; break; } } } cnt += (Int32)relocation.SizeOfBlock; relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, (UInt32)(directory.VirtualAddress + cnt)); } } }
public void OffsetIsBiggerThanBuffer_Test() { var ibr = new IMAGE_BASE_RELOCATION(RawStructures.RawImageBaseRelocation, 1234, 12); }
public void SizeOfBlockIsBiggerThanRelocDirSize_Test() { var rawImageBaseRelocBroken = new byte[] { 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x30, 0xC4, 0x30 }; var ibr = new IMAGE_BASE_RELOCATION(rawImageBaseRelocBroken, 0, 0); }
public void SerializeDirectoryInfo_Correct() { //arrange var imageBaseRelocation = new ImageBaseRelocationSerializer(new TypeOffsetSerializer()); var buffer = new byte[100]; ulong bufferOffset = 0; var relocationOffsetList = new List <RelocationTypeOffset>() { new RelocationTypeOffset() { Type = 0x3, Offset = 0x1000 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1020 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1123 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1300 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1300 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1411 }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1a1f }, new RelocationTypeOffset() { Type = 0x3, Offset = 0x1FFF }, }; //act imageBaseRelocation.Serialize(buffer, ref bufferOffset, relocationOffsetList); //assert try { var relocationDirectory = new IMAGE_BASE_RELOCATION(buffer, 0, (uint)relocationOffsetList.Count * 2 + 8); Assert.AreEqual((int)relocationDirectory.SizeOfBlock, 0x18); Assert.AreEqual((int)relocationDirectory.VirtualAddress, 0x1000); Assert.AreEqual(relocationDirectory.TypeOffsets.Length, 8); Assert.AreEqual(relocationDirectory.TypeOffsets[0].Type, 0x3); Assert.AreEqual(relocationDirectory.TypeOffsets[0].Offset, 0x000); Assert.AreEqual(relocationDirectory.TypeOffsets[1].Type, 0x3); Assert.AreEqual(relocationDirectory.TypeOffsets[1].Offset, 0x020); Assert.AreEqual(relocationDirectory.TypeOffsets[7].Type, 0x3); Assert.AreEqual(relocationDirectory.TypeOffsets[7].Offset, 0xFFF); } catch (Exception ex) { Assert.Fail("failed to serialize relocation directory: exception", ex.ToString()); } }