From 9076b2429ce25697b96c7ad2d6decc09a63b4578 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Mon, 13 Dec 2021 14:52:24 -0500 Subject: [PATCH] GP-1571 ELF: create fake relocation table entry for non-relocation memory modifications (needed for ELF export) --- .../format/elf/ElfDefaultGotPltMarkup.java | 2 ++ .../util/bin/format/elf/ElfLoadHelper.java | 17 ++++++++-- .../app/util/opinion/ElfProgramBuilder.java | 28 +++++++++++++++- .../format/elf/extend/MIPS_ElfExtension.java | 33 +++++++++++-------- .../elf/extend/PowerPC_ElfExtension.java | 3 +- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java index be7b097223..8670f3fbd4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java @@ -378,9 +378,11 @@ public class ElfDefaultGotPltMarkup { // TODO: record artificial relative relocation for reversion/export concerns entry1Value += imageBaseAdj; // adjust first entry value if (elf.is64Bit()) { + elfLoadHelper.addFakeRelocTableEntry(gotStart, 8); memory.setLong(gotStart, entry1Value); } else { + elfLoadHelper.addFakeRelocTableEntry(gotStart, 4); memory.setInt(gotStart, (int) entry1Value); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java index cff05fe218..e625b2b7db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java @@ -17,8 +17,7 @@ package ghidra.app.util.bin.format.elf; import ghidra.app.util.bin.format.MemoryLoadable; import ghidra.app.util.importer.MessageLog; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; +import ghidra.program.model.address.*; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryAccessException; @@ -203,4 +202,18 @@ public interface ElfLoadHelper { public long getOriginalValue(Address addr, boolean signExtend) throws MemoryAccessException; + /** + * Add a fake relocation table entry if none previously existed for the specified address. + * This is intended to record original file bytes when forced modifications have been + * performed during the ELF import processing. A relocation type of 0 will be specified for + * fake entry. + * @param address relocation address + * @param length number of bytes affected + * @return true if recorded successfully, or false if conflict with existing relocation entry occurs + * @throws MemoryAccessException if unable to read bytes from memory + * @throws AddressOverflowException if range address wrap occurs + */ + public boolean addFakeRelocTableEntry(Address address, int length) + throws MemoryAccessException, AddressOverflowException; + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 1159e134ea..51c8f16197 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -846,6 +846,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { monitor.checkCanceled(); monitor.incrementProgress(1); + long type = reloc.getType(); + if (type == 0) { + continue; // ignore relocation type 0 (i.e., ..._NONE) + } + int symbolIndex = reloc.getSymbolIndex(); String symbolName = null; if (symbolIndex >= 0 && symbolIndex < symbols.length) { @@ -863,7 +868,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4]; - long type = reloc.getType(); if (relrRelocationType != 0) { type = relrRelocationType; reloc.setType(relrRelocationType); @@ -929,6 +933,28 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { : dataConverter.getValue(bytes, len); } + @Override + public boolean addFakeRelocTableEntry(Address address, int length) + throws MemoryAccessException, AddressOverflowException { + byte[] bytes = new byte[length]; + Address maxAddr = address.addNoWrap(length - 1); + RelocationTable relocationTable = program.getRelocationTable(); + Relocation relocation = relocationTable.getRelocation(address); + if (relocation != null) { + return false; + } + relocation = relocationTable.getRelocationAfter(address); + if (relocation != null && relocation.getAddress().compareTo(maxAddr) <= 0) { + return false; + } + int cnt = memory.getBytes(address, bytes); + if (cnt != length) { + throw new MemoryAccessException(); + } + relocationTable.add(address, 0, new long[0], bytes, null); + return true; + } + /** * Add reference to previously applied header structure (assumes markupElfHeader previously called) * @param componentName diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java index efba3dcb7b..0301de5ab1 100644 --- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java +++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java @@ -454,7 +454,7 @@ public class MIPS_ElfExtension extends ElfExtension { setTableEntryIfZero(gotBaseAddress, gotIndex, symbolOffset, elfLoadHelper); } - catch (MemoryAccessException e) { + catch (MemoryAccessException | AddressOverflowException e) { Msg.error(this, "Failed to update .got table entry", e); } catch (NotFoundException e) { @@ -793,7 +793,7 @@ public class MIPS_ElfExtension extends ElfExtension { catch (NotFoundException e) { throw new AssertException("unexpected", e); } - catch (MemoryAccessException e) { + catch (MemoryAccessException | AddressOverflowException e) { elfLoadHelper.log("Failed to adjust GOT: " + e.getMessage()); } } @@ -846,37 +846,42 @@ public class MIPS_ElfExtension extends ElfExtension { catch (NotFoundException e) { throw new AssertException("unexpected", e); } - catch (MemoryAccessException e) { + catch (MemoryAccessException | AddressOverflowException e) { elfLoadHelper.log("Failed to adjust MIPS GOT: " + e.getMessage()); } } private Address adjustTableEntryIfNonZero(Address tableBaseAddr, int entryIndex, - long adjustment, ElfLoadHelper elfLoadHelper) throws MemoryAccessException { - // TODO: record artificial relative relocation for reversion/export concerns + long adjustment, ElfLoadHelper elfLoadHelper) + throws MemoryAccessException, AddressOverflowException { boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit(); Memory memory = elfLoadHelper.getProgram().getMemory(); Address tableEntryAddr; if (is64Bit) { tableEntryAddr = tableBaseAddr.add(entryIndex * 8); - long offset = memory.getLong(tableEntryAddr); - if (offset != 0) { - memory.setLong(tableEntryAddr, offset + adjustment); + if (adjustment != 0) { + long offset = memory.getLong(tableEntryAddr); + if (offset != 0) { + elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 8); + memory.setLong(tableEntryAddr, offset + adjustment); + } } } else { tableEntryAddr = tableBaseAddr.add(entryIndex * 4); - int offset = memory.getInt(tableEntryAddr); - if (offset != 0) { - memory.setInt(tableEntryAddr, (int) (offset + adjustment)); + if (adjustment != 0) { + int offset = memory.getInt(tableEntryAddr); + if (offset != 0) { + elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 4); + memory.setInt(tableEntryAddr, (int) (offset + adjustment)); + } } } return tableEntryAddr; } private Address setTableEntryIfZero(Address tableBaseAddr, int entryIndex, long value, - ElfLoadHelper elfLoadHelper) throws MemoryAccessException { - // TODO: record artificial relative relocation for reversion/export concerns + ElfLoadHelper elfLoadHelper) throws MemoryAccessException, AddressOverflowException { boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit(); Memory memory = elfLoadHelper.getProgram().getMemory(); Address tableEntryAddr; @@ -884,6 +889,7 @@ public class MIPS_ElfExtension extends ElfExtension { tableEntryAddr = tableBaseAddr.add(entryIndex * 8); long offset = memory.getLong(tableEntryAddr); if (offset == 0) { + elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 8); memory.setLong(tableEntryAddr, value); } } @@ -891,6 +897,7 @@ public class MIPS_ElfExtension extends ElfExtension { tableEntryAddr = tableBaseAddr.add(entryIndex * 4); int offset = memory.getInt(tableEntryAddr); if (offset == 0) { + elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 4); memory.setInt(tableEntryAddr, (int) value); } } diff --git a/Ghidra/Processors/PowerPC/src/main/java/ghidra/app/util/bin/format/elf/extend/PowerPC_ElfExtension.java b/Ghidra/Processors/PowerPC/src/main/java/ghidra/app/util/bin/format/elf/extend/PowerPC_ElfExtension.java index f16f1cb22b..c783f20e86 100644 --- a/Ghidra/Processors/PowerPC/src/main/java/ghidra/app/util/bin/format/elf/extend/PowerPC_ElfExtension.java +++ b/Ghidra/Processors/PowerPC/src/main/java/ghidra/app/util/bin/format/elf/extend/PowerPC_ElfExtension.java @@ -113,9 +113,10 @@ public class PowerPC_ElfExtension extends ElfExtension { // Update first got entry normally updated by link editor to refer to dynamic table int dynamicOffset = memory.getInt(gotAddr) + (int) elfLoadHelper.getImageBaseWordAdjustmentOffset(); + elfLoadHelper.addFakeRelocTableEntry(gotAddr, 4); memory.setInt(gotAddr, dynamicOffset); } - catch (MemoryAccessException e) { + catch (MemoryAccessException | AddressOverflowException e) { elfLoadHelper.log(e); } }