diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/LoadConfigDirectory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/LoadConfigDirectory.java index 27d1ca50aa..0bc5a144cc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/LoadConfigDirectory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/LoadConfigDirectory.java @@ -160,7 +160,7 @@ public class LoadConfigDirectory implements StructConverter { if (section != null) { long fileOffset = section.getPointerToRawData() + dynamicValueRelocTableOffset; long rva = section.getVirtualAddress() + dynamicValueRelocTableOffset; - dvrt = new ImageDynamicRelocationTable(reader.clone(fileOffset), rva); + dvrt = new ImageDynamicRelocationTable(reader.clone(fileOffset), rva, is64bit); } else { Msg.error(this, diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/DvrtType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/DvrtType.java index 30d15210d4..0e230bc5d1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/DvrtType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/DvrtType.java @@ -35,17 +35,20 @@ public enum DvrtType implements StructConverter { IMAGE_DYNAMIC_RELOCATION_SWITCHABLE_BRANCH(0x5), IMAGE_DYNAMIC_RELOCATION_ARM64X(0x6), IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE(0x7), - IMAGE_DYNAMIC_RELOCATION_ARM64_KERNEL_IMPORT_CALL_TRANSFER(0x8); + IMAGE_DYNAMIC_RELOCATION_ARM64_KERNEL_IMPORT_CALL_TRANSFER(0x8), + IMAGE_DYNAMIC_RELOCATION_UNKNOWN(0x100); // made up to handle unknown types private long value; + private int size; /** - * Creates a new {@link DvrtType} + * Creates a new 8-byte {@link DvrtType} * * @param value The defined value of the type */ - private DvrtType(int value) { + private DvrtType(long value) { this.value = value; + this.size = 8; } /** @@ -56,24 +59,51 @@ public enum DvrtType implements StructConverter { } /** - * Reads a {@link DvrtType} + * Changes the size of this {@link DvrtType} to the given number of bytes + * + * @param n The new size in bytes + * @return This {@link DvrtType}, with the new size applied + */ + public DvrtType changeSize(int n) { + this.size = n; + return this; + } + + /** + * Reads an 8-byte {@link DvrtType} * * @param reader A {@link BinaryReader} that points to the start of the type value - * @return The type that was read, or {@code null} if the value read does not correspond to a - * valid type + * @return The type that was read, or {@link #IMAGE_DYNAMIC_RELOCATION_UNKNOWN} if the value + * read does not correspond to a known type * @throws IOException if there was an IO-related error */ - public static DvrtType type(BinaryReader reader) throws IOException { + public static DvrtType type8(BinaryReader reader) throws IOException { long value = reader.readNextLong(); return Arrays.stream(DvrtType.values()) .filter(e -> value == e.getValue()) .findFirst() - .orElse(null); + .orElse(IMAGE_DYNAMIC_RELOCATION_UNKNOWN); + } + + /** + * Reads a 4-byte {@link DvrtType} + * + * @param reader A {@link BinaryReader} that points to the start of the type value + * @return The type that was read, or {@link #IMAGE_DYNAMIC_RELOCATION_UNKNOWN} if the value + * read does not correspond to a known type + * @throws IOException if there was an IO-related error + */ + public static DvrtType type4(BinaryReader reader) throws IOException { + int value = reader.readNextInt(); + return Arrays.stream(DvrtType.values()) + .filter(e -> value == e.getValue()) + .findFirst() + .orElse(IMAGE_DYNAMIC_RELOCATION_UNKNOWN); } @Override public DataType toDataType() throws DuplicateNameException, IOException { - EnumDataType enumDt = new EnumDataType("DvrtType", 8); + EnumDataType enumDt = new EnumDataType("DvrtType", size); Arrays.stream(values()).forEach(e -> enumDt.add(e.name(), e.getValue())); enumDt.setCategoryPath(new CategoryPath("/PE")); return enumDt; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocation.java index ffdc97b593..821b42ebf8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocation.java @@ -40,6 +40,7 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable { private int baseRelocSize; private long rva; + private boolean is64bit; private List headers = new ArrayList<>(); /** @@ -47,13 +48,17 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable { * * @param reader A {@link BinaryReader} that points to the start of the structure * @param rva The relative virtual address of the structure + * @param is64bit True if 64-bit; otherwise, false * @throws IOException if there was an IO-related error */ - public ImageDynamicRelocation(BinaryReader reader, long rva) throws IOException { + public ImageDynamicRelocation(BinaryReader reader, long rva, boolean is64bit) + throws IOException { this.rva = rva; + this.is64bit = is64bit; long origIndex = reader.getPointerIndex(); - symbol = reader.readNext(DvrtType::type); + symbol = is64bit ? reader.readNext(DvrtType::type8) + : reader.readNext(DvrtType::type4).changeSize(4); baseRelocSize = reader.readNextInt(); long startIndex = reader.getPointerIndex(); @@ -69,7 +74,8 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable { case IMAGE_DYNAMIC_RELOCATION_ARM64X -> new ImageArm64X(reader, newRva); case IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE -> new ImageFunctionOverrideHeader( reader, newRva, baseRelocSize); - case null -> new ImageUnsupportedRelocationHeader(reader, newRva, baseRelocSize); + case IMAGE_DYNAMIC_RELOCATION_UNKNOWN -> new ImageUnsupportedRelocationHeader( + reader, newRva, baseRelocSize); default -> new ImageUnsupportedRelocationHeader(reader, newRva, baseRelocSize); }); } @@ -100,14 +106,19 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable { for (AbstractImageDynamicRelocationHeader header : headers) { header.markup(program, isBinary, monitor, log, ntHeader); } - listing.setComment(start, CommentType.PLATE, - symbol != null ? symbol.name() : "IMAGE_DYNAMIC_RELOCATION_"); + listing.setComment(start, CommentType.PLATE, symbol.name()); } @Override public DataType toDataType() throws DuplicateNameException, IOException { - StructureDataType struct = new StructureDataType("IMAGE_DYNAMIC_RELOCATION", 0); - struct.add(symbol != null ? symbol.toDataType() : QWORD, "Symbol", null); + String name ="IMAGE_DYNAMIC_RELOCATION"; + DataType symbolType = symbol.toDataType(); + if (symbol == DvrtType.IMAGE_DYNAMIC_RELOCATION_UNKNOWN) { + name += "_UNKNOWN"; + symbolType = is64bit ? QWORD : DWORD; + } + StructureDataType struct = new StructureDataType(name, 0); + struct.add(symbolType, "Symbol", null); struct.add(DWORD, "BaseRelocSize", null); struct.setCategoryPath(new CategoryPath("/PE")); return struct; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocationTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocationTable.java index 62e08a8f0f..48339e1477 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocationTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/dvrt/ImageDynamicRelocationTable.java @@ -47,18 +47,25 @@ public class ImageDynamicRelocationTable implements StructConverter, PeMarkupabl * * @param reader A {@link BinaryReader} that points to the start of the structure * @param rva The relative virtual address of the structure + * @param is64bit True if 64-bit; otherwise, false * @throws IOException if there was an IO-related error */ - public ImageDynamicRelocationTable(BinaryReader reader, long rva) throws IOException { + public ImageDynamicRelocationTable(BinaryReader reader, long rva, boolean is64bit) + throws IOException { this.rva = rva; long origIndex = reader.getPointerIndex(); version = reader.readNextInt(); size = reader.readNextInt(); + if (version != 1) { + // TODO: support version 2 + return; + } + long startIndex = reader.getPointerIndex(); for (long i = startIndex; i < startIndex + size; i = reader.getPointerIndex()) { - relocations.add(new ImageDynamicRelocation(reader, rva + (i - origIndex))); + relocations.add(new ImageDynamicRelocation(reader, rva + (i - origIndex), is64bit)); } }