GP-6502: A few more PE Dynamic Value Relocation Table (DVRT)

improvements
This commit is contained in:
Ryan Kurtz
2026-02-27 08:33:10 -05:00
parent ddd94b932c
commit d06b9d1f1d
4 changed files with 67 additions and 19 deletions
@@ -160,7 +160,7 @@ public class LoadConfigDirectory implements StructConverter {
if (section != null) { if (section != null) {
long fileOffset = section.getPointerToRawData() + dynamicValueRelocTableOffset; long fileOffset = section.getPointerToRawData() + dynamicValueRelocTableOffset;
long rva = section.getVirtualAddress() + dynamicValueRelocTableOffset; long rva = section.getVirtualAddress() + dynamicValueRelocTableOffset;
dvrt = new ImageDynamicRelocationTable(reader.clone(fileOffset), rva); dvrt = new ImageDynamicRelocationTable(reader.clone(fileOffset), rva, is64bit);
} }
else { else {
Msg.error(this, Msg.error(this,
@@ -35,17 +35,20 @@ public enum DvrtType implements StructConverter {
IMAGE_DYNAMIC_RELOCATION_SWITCHABLE_BRANCH(0x5), IMAGE_DYNAMIC_RELOCATION_SWITCHABLE_BRANCH(0x5),
IMAGE_DYNAMIC_RELOCATION_ARM64X(0x6), IMAGE_DYNAMIC_RELOCATION_ARM64X(0x6),
IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE(0x7), 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 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 * @param value The defined value of the type
*/ */
private DvrtType(int value) { private DvrtType(long value) {
this.value = 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 * @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 * @return The type that was read, or {@link #IMAGE_DYNAMIC_RELOCATION_UNKNOWN} if the value
* valid type * read does not correspond to a known type
* @throws IOException if there was an IO-related error * @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(); long value = reader.readNextLong();
return Arrays.stream(DvrtType.values()) return Arrays.stream(DvrtType.values())
.filter(e -> value == e.getValue()) .filter(e -> value == e.getValue())
.findFirst() .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 @Override
public DataType toDataType() throws DuplicateNameException, IOException { 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())); Arrays.stream(values()).forEach(e -> enumDt.add(e.name(), e.getValue()));
enumDt.setCategoryPath(new CategoryPath("/PE")); enumDt.setCategoryPath(new CategoryPath("/PE"));
return enumDt; return enumDt;
@@ -40,6 +40,7 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable {
private int baseRelocSize; private int baseRelocSize;
private long rva; private long rva;
private boolean is64bit;
private List<AbstractImageDynamicRelocationHeader> headers = new ArrayList<>(); private List<AbstractImageDynamicRelocationHeader> 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 reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address 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 * @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.rva = rva;
this.is64bit = is64bit;
long origIndex = reader.getPointerIndex(); long origIndex = reader.getPointerIndex();
symbol = reader.readNext(DvrtType::type); symbol = is64bit ? reader.readNext(DvrtType::type8)
: reader.readNext(DvrtType::type4).changeSize(4);
baseRelocSize = reader.readNextInt(); baseRelocSize = reader.readNextInt();
long startIndex = reader.getPointerIndex(); 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_ARM64X -> new ImageArm64X(reader, newRva);
case IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE -> new ImageFunctionOverrideHeader( case IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE -> new ImageFunctionOverrideHeader(
reader, newRva, baseRelocSize); 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); default -> new ImageUnsupportedRelocationHeader(reader, newRva, baseRelocSize);
}); });
} }
@@ -100,14 +106,19 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable {
for (AbstractImageDynamicRelocationHeader header : headers) { for (AbstractImageDynamicRelocationHeader header : headers) {
header.markup(program, isBinary, monitor, log, ntHeader); header.markup(program, isBinary, monitor, log, ntHeader);
} }
listing.setComment(start, CommentType.PLATE, listing.setComment(start, CommentType.PLATE, symbol.name());
symbol != null ? symbol.name() : "IMAGE_DYNAMIC_RELOCATION_<UNKNOWN>");
} }
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_DYNAMIC_RELOCATION", 0); String name ="IMAGE_DYNAMIC_RELOCATION";
struct.add(symbol != null ? symbol.toDataType() : QWORD, "Symbol", null); 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.add(DWORD, "BaseRelocSize", null);
struct.setCategoryPath(new CategoryPath("/PE")); struct.setCategoryPath(new CategoryPath("/PE"));
return struct; return struct;
@@ -47,18 +47,25 @@ public class ImageDynamicRelocationTable implements StructConverter, PeMarkupabl
* *
* @param reader A {@link BinaryReader} that points to the start of the structure * @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address 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 * @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; this.rva = rva;
long origIndex = reader.getPointerIndex(); long origIndex = reader.getPointerIndex();
version = reader.readNextInt(); version = reader.readNextInt();
size = reader.readNextInt(); size = reader.readNextInt();
if (version != 1) {
// TODO: support version 2
return;
}
long startIndex = reader.getPointerIndex(); long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + size; i = 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));
} }
} }