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) {
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,
@@ -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;
@@ -40,6 +40,7 @@ public class ImageDynamicRelocation implements StructConverter, PeMarkupable {
private int baseRelocSize;
private long rva;
private boolean is64bit;
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 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_<UNKNOWN>");
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;
@@ -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));
}
}