GP-6502: The PE Dynamic Value Relocation Table (DVRT) is now parsed and

marked up
This commit is contained in:
Ryan Kurtz
2026-02-23 12:19:04 -05:00
parent 695060e911
commit 3080cd612e
21 changed files with 1950 additions and 95 deletions
@@ -20,9 +20,14 @@ import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.DataConverter;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* A class to represent the <code>IMAGE_BASE_RELOCATION</code>
@@ -66,24 +71,36 @@ public class BaseRelocation implements StructConverter, ByteArrayConverter {
/**
* Names of the available base relocations.
*/
public final static String [] TYPE_STRINGS = {
"ABSOLUTE", // 0
"HIGH", // 1
"LOW", // 2
"HIGHLOW", // 3
"HIGHADJ", // 4
"MIPS_JMPADDR", // 5
"???6",
"???7",
"???8",
"IA64_IMM64", // 9
"DIR64", // 10
};
public final static String[] TYPE_STRINGS = {
"ABSOLUTE",
"HIGH",
"LOW",
"HIGHLOW",
"HIGHADJ",
"MIPS_JMPADDR",
"RESERVED",
"THUMB_MOV32",
"RISCV_LOW12S",
"MIPS_JMPADDR16",
"DIR64"
};
private int virtualAddress;
private int sizeOfBlock;
private List<TypeOffset> typeOffsetList = new ArrayList<TypeOffset>();
public BaseRelocation(BinaryReader reader) throws IOException {
virtualAddress = reader.readNextInt();
sizeOfBlock = reader.readNextInt();
int len = (sizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / BinaryReader.SIZEOF_SHORT;
for (int i = 0; i < len; ++i) {
short typeOffset = reader.readNextShort();
typeOffsetList.add(new TypeOffset(typeOffset));
}
}
BaseRelocation(BinaryReader reader, int index) throws IOException {
virtualAddress = reader.readInt(index); index += BinaryReader.SIZEOF_INT;
sizeOfBlock = reader.readInt(index); index += BinaryReader.SIZEOF_INT;
@@ -139,12 +156,22 @@ public class BaseRelocation implements StructConverter, ByteArrayConverter {
return typeOffsetList.size();
}
/**
* Returns the {@link TypeOffset}
*
* @param index the ith relocation
* @return the {@link TypeOffset} of the relocation
*/
public TypeOffset getTypeOffset(int index) {
return typeOffsetList.get(index);
}
/**
* Returns the lower 12 bits of the offset.
*
* @param index the ith relocation
* @return int the offset of the relocation
*/
* Returns the lower 12 bits of the offset.
*
* @param index the ith relocation
* @return the offset of the relocation
*/
public int getOffset(int index) {
return typeOffsetList.get(index).offset;
}
@@ -153,19 +180,51 @@ public class BaseRelocation implements StructConverter, ByteArrayConverter {
* Returns the upper 4 bits of the offset.
*
* @param index the ith relocation
* @return int the type of the relocation
, */
* @return the type of the relocation
*/
public int getType(int index) {
return typeOffsetList.get(index).type;
}
public String getName(int type) {
return (type >= 0 && type < TYPE_STRINGS.length) ? TYPE_STRINGS[type] : "<UNKNOWN TYPE>";
}
public void markup(Program program, Address addr, boolean isBinary, TaskMonitor monitor,
MessageLog log, NTHeader ntHeader) throws DuplicateNameException, IOException {
ReferenceManager refMgr = program.getReferenceManager();
Listing listing = program.getListing();
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (TypeOffset typeOffset : typeOffsetList) {
if (monitor.isCancelled()) {
return;
}
DataType typeOffsetDt = typeOffset.toDataType();
PeUtils.createData(program, addr, typeOffsetDt, log);
if (typeOffset.typeOffset != 0) {
refMgr.addMemoryReference(addr, imageBase.add(virtualAddress + typeOffset.offset),
RefType.DATA, SourceType.IMPORTED, 0);
listing.setComment(addr, CommentType.EOL, getName(typeOffset.type));
}
else {
listing.setComment(addr, CommentType.EOL, "padding");
}
addr = addr.add(typeOffsetDt.getLength());
}
}
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(NAME, 0);
struct.add(DWORD,"VirtualAddress",null);
struct.add(IBO32, "VirtualAddress", null);
struct.add(DWORD,"SizeOfBlock",null);
struct.add(new ArrayDataType(WORD, typeOffsetList.size(), WORD.getLength()),"TypeOffset",null);
struct.setCategoryPath(new CategoryPath("/PE"));
@@ -188,7 +247,7 @@ public class BaseRelocation implements StructConverter, ByteArrayConverter {
return bytes;
}
private class TypeOffset {
public class TypeOffset implements StructConverter {
short typeOffset;
int type;
int offset;
@@ -204,5 +263,21 @@ public class BaseRelocation implements StructConverter, ByteArrayConverter {
this.type = type;
this.offset = offset;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
// StructureDataType struct = new StructureDataType("TypeOffset", 4);
// struct.setPackingEnabled(true);
// try {
// struct.addBitField(WORD, 12, "Offset", null);
// struct.addBitField(WORD, 4, "Type", null);
// }
// catch (InvalidDataTypeException e) {
// throw new IOException(e);
// }
// struct.setCategoryPath(new CategoryPath("/PE"));
// return struct;
return WORD;
}
}
}
@@ -23,11 +23,11 @@ import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteArrayConverter;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DWordDataType;
import ghidra.program.model.data.WordDataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.DataConverter;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
@@ -51,7 +51,8 @@ public class BaseRelocationDataDirectory extends DataDirectory implements ByteAr
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader nt) throws CodeUnitInsertionException {
NTHeader nt) throws CodeUnitInsertionException, DuplicateNameException, IOException,
MemoryAccessException {
monitor.setMessage(program.getName()+": base relocation(s)...");
Address addr = PeUtils.getMarkupAddress(program, isBinary, nt, virtualAddress);
@@ -59,26 +60,13 @@ public class BaseRelocationDataDirectory extends DataDirectory implements ByteAr
return;
}
createDirectoryBookmark(program, addr);
for (BaseRelocation reloc : relocs) {
if (monitor.isCancelled()) {
return;
}
PeUtils.createData(program, addr, DWordDataType.dataType, log);
addr = addr.add(DWordDataType.dataType.getLength());
PeUtils.createData(program, addr, DWordDataType.dataType, log);
addr = addr.add(DWordDataType.dataType.getLength());
int count = reloc.getCount();
for (int j = 0 ; j < count ; ++j) {
if (monitor.isCancelled()) {
return;
}
PeUtils.createData(program, addr, WordDataType.dataType, log);
addr = addr.add(WordDataType.dataType.getLength());
}
reloc.markup(program, addr, isBinary, monitor, log, nt);
addr = addr.add(reloc.getSizeOfBlock());
}
}
@@ -18,10 +18,12 @@ package ghidra.app.util.bin.format.pe;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.dvrt.ImageDynamicRelocationTable;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
@@ -50,7 +52,8 @@ public class LoadConfigDataDirectory extends DataDirectory {
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader nt) throws DuplicateNameException, CodeUnitInsertionException, IOException {
NTHeader nt) throws DuplicateNameException, CodeUnitInsertionException, IOException,
MemoryAccessException {
monitor.setMessage(program.getName()+": load config directory...");
@@ -64,6 +67,11 @@ public class LoadConfigDataDirectory extends DataDirectory {
markupSeHandler(program, isBinary, monitor, log, nt);
ControlFlowGuard.markup(lcd, program, log, nt);
ImageDynamicRelocationTable dvrt = lcd.getDynamicRelocationTable();
if (dvrt != null) {
dvrt.markup(program, isBinary, monitor, log, nt);
}
}
private void markupSeHandler(Program program, boolean isBinary, TaskMonitor monitor,
@@ -100,7 +108,7 @@ public class LoadConfigDataDirectory extends DataDirectory {
return false;
}
lcd = new LoadConfigDirectory(reader, ptr, ntHeader.getOptionalHeader());
lcd = new LoadConfigDirectory(reader, ptr, ntHeader);
return true;
}
}
@@ -19,7 +19,9 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.dvrt.ImageDynamicRelocationTable;
import ghidra.program.model.data.*;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
/**
@@ -74,9 +76,12 @@ public class LoadConfigDirectory implements StructConverter {
private long reserved3;
private boolean is64bit;
private ImageDynamicRelocationTable dvrt;
LoadConfigDirectory(BinaryReader reader, int index, OptionalHeader oh) throws IOException {
is64bit = oh.is64bit();
LoadConfigDirectory(BinaryReader reader, int index, NTHeader nt) throws IOException {
FileHeader fh = nt.getFileHeader();
OptionalHeader oh = nt.getOptionalHeader();
is64bit = nt.getOptionalHeader().is64bit();
long oldIndex = reader.getPointerIndex();
reader.setPointerIndex(index);
@@ -149,143 +154,139 @@ public class LoadConfigDirectory implements StructConverter {
reserved2 = reader.readNextInt();
reserved3 = readPointer(reader);
}
if (dynamicValueRelocTableOffset != 0 && dynamicValueRelocTableSection != 0) {
SectionHeader section = fh.getSectionHeader(dynamicValueRelocTableSection - 1);
if (section != null) {
long fileOffset = section.getPointerToRawData() + dynamicValueRelocTableOffset;
long rva = section.getVirtualAddress() + dynamicValueRelocTableOffset;
dvrt = new ImageDynamicRelocationTable(reader.clone(fileOffset), rva);
}
else {
Msg.error(this,
"Dynamic value relocation table specifies invalid section number: " +
dynamicValueRelocTableSection);
}
}
reader.setPointerIndex(oldIndex);
}
/**
* Returns the size (in bytes) of this structure.
*
* @return the size (in bytes) of this structure
* {@return the size (in bytes) of this structure}
*/
public int getSize() {
return size;
}
/**
* Returns the critical section default time-out value.
*
* @return the critical section default time-out value
* {@return the critical section default time-out value}
*/
public int getCriticalSectionDefaultTimeout() {
return criticalSectionDefaultTimeout;
}
/**
* Gets the safe exception handler table.
*
* @return the safe exception handler table.
* {@return the safe exception handler table}
*/
public long getSeHandlerTable() {
return seHandlerTable;
}
/**
* Gets the safe exception handler table count.
*
* @return the safe exception handler table count.
* {@return the safe exception handler table count}
*/
public long getSeHandlerCount() {
return seHandlerCount;
}
/**
* Gets the ControlFlowGuard {@link GuardFlags}.
*
* @return The ControlFlowGuard {@link GuardFlags}.
* {@return the ControlFlowGuard {@link GuardFlags}}
*/
public GuardFlags getCfgGuardFlags() {
return guardFlags;
}
/**
* Gets the ControlFlowGuard check function pointer address.
*
* @return The ControlFlowGuard check function pointer address.
* Could be 0 if ControlFlowGuard is not being used.
* {@return the ControlFlowGuard check function pointer address (could be 0 if ControlFlowGuard
* is not being used)}
*/
public long getCfgCheckFunctionPointer() {
return guardCfcCheckFunctionPointer;
}
/**
* Gets the ControlFlowGuard dispatch function pointer address.
*
* @return The ControlFlowGuard dispatch function pointer address.
* Could be 0 if ControlFlowGuard is not being used.
* {@return the ControlFlowGuard dispatch function pointer address (could be 0 if
* ControlFlowGuard is not being used)}
*/
public long getCfgDispatchFunctionPointer() {
return guardCfDispatchFunctionPointer;
}
/**
* Gets the ControlFlowGuard function table pointer address.
*
* @return The ControlFlowGuard function table function pointer address.
* Could be 0 if ControlFlowGuard is not being used.
* {@return the ControlFlowGuard function table function pointer address (could be 0 if
* ControlFlowGuard is not being used)}
*/
public long getCfgFunctionTablePointer() {
return guardCfFunctionTable;
}
/**
* Gets the ControlFlowGuard function count.
*
* @return The ControlFlowGuard function count. Could be 0 if ControlFlowGuard is
* not being used.
* {@return the ControlFlowGuard function count (could be 0 if ControlFlowGuard is not being
* used)}
*/
public long getCfgFunctionCount() {
return guardCfFunctionCount;
}
/**
* Gets the ControlFlowGuard IAT table pointer address.
*
* @return The ControlFlowGuard IAT table function pointer address. Could be 0 if ControlFlowGuard is not being used
* {@return the ControlFlowGuard IAT table function pointer address (could be 0 if
* ControlFlowGuard is not being used)}
*/
public long getGuardAddressIatTableTablePointer() {
return guardAddressTakenIatEntryTable;
}
/**
* Gets the ControlFlowGuard IAT entries count.
*
* @return The ControlFlowGuard IAT entries count. Could be 0 if ControlFlowGuard is not being used
* {@return the ControlFlowGuard IAT entries count (could be 0 if ControlFlowGuard is not being
* used)}
*/
public long getGuardAddressIatTableCount() {
return guardAddressTakenIatEntryCount;
}
/**
* Gets the ReturnFlowGuard failure routine address.
*
* @return The ReturnFlowGuard failure routine address.
* Could be 0 if ReturnFlowGuard is not being used.
* {@return the ReturnFlowGuard failure routine address (could be 0 if ReturnFlowGuard is not
* being used)}
*/
public long getRfgFailureRoutine() {
return guardRfFailureRoutine;
}
/**
* Gets the ReturnFlowGuard failure routine function pointer address.
*
* @return The ReturnFlowGuard failure routine function pointer address.
* Could be 0 if ReturnFlowGuard is not being used.
* {@return the ReturnFlowGuard failure routine function pointer address (could be 0 if
* ReturnFlowGuard is not being used)}
*/
public long getRfgFailureRoutineFunctionPointer() {
return guardRfFailureRoutineFunctionPointer;
}
/**
* Gets the ReturnFlowGuard verify stack pointer function pointer address.
*
* @return The ReturnFlowGuard verify stack pointer function pointer address.
* Could be 0 if ReturnFlowGuard is not being used.
* {@return the ReturnFlowGuard verify stack pointer function pointer address (could be 0 if
* ReturnFlowGuard is not being used)}
*/
public long getRfgVerifyStackPointerFunctionPointer() {
return guardRfVerifyStackPointerFunctionPointer;
}
/**
* {@return the Dynamic Value Relocation Table (could be {@code null} if DVRT is not being
* used)}
*/
public ImageDynamicRelocationTable getDynamicRelocationTable() {
return dvrt;
}
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(is64bit ? NAME64 : NAME32, 0);
@@ -0,0 +1,40 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.PeMarkupable;
/**
* An abstract dynamic value relocation header
*/
public abstract class AbstractImageDynamicRelocationHeader
implements StructConverter, PeMarkupable {
protected long rva;
/**
* Creates a new {@link AbstractImageDynamicRelocationHeader}
*
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public AbstractImageDynamicRelocationHeader(long rva) throws IOException {
this.rva = rva;
}
}
@@ -0,0 +1,81 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.Arrays;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Defined symbol dynamic relocation entries
*/
public enum DvrtType implements StructConverter {
IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE(0x1),
IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE(0x2),
IMAGE_DYNAMIC_RELOCATION_IMPORT_CONTROL_TRANSFER(0x3),
IMAGE_DYNAMIC_RELOCATION_INDIR_CONTROL_TRANSFER(0x4),
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);
private long value;
/**
* Creates a new {@link DvrtType}
*
* @param value The defined value of the type
*/
private DvrtType(int value) {
this.value = value;
}
/**
* {@return the type's defined value}
*/
public long getValue() {
return value;
}
/**
* Reads a {@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
* @throws IOException if there was an IO-related error
*/
public static DvrtType type(BinaryReader reader) throws IOException {
long value = reader.readNextLong();
return Arrays.stream(DvrtType.values())
.filter(e -> value == e.getValue())
.findFirst()
.orElse(null);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
EnumDataType enumDt = new EnumDataType("DvrtType", 8);
Arrays.stream(values()).forEach(e -> enumDt.add(e.name(), e.getValue()));
enumDt.setCategoryPath(new CategoryPath("/PE"));
return enumDt;
}
}
@@ -0,0 +1,114 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Contains a list of {@link ImageArm64XDynamicRelocation}s
*/
public class ImageArm64X extends AbstractImageDynamicRelocationHeader {
private int virtualAddress;
private int sizeOfBlock;
private List<ImageArm64XDynamicRelocation> relocs = new ArrayList<>();
/**
* Creates a new {@link ImageIndirControlTransfer}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageArm64X(BinaryReader reader, long rva) throws IOException {
super(rva);
long origIndex = reader.getPointerIndex();
virtualAddress = reader.readNextInt();
sizeOfBlock = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < origIndex + sizeOfBlock; i = reader.getPointerIndex()) {
relocs.add(new ImageArm64XDynamicRelocation(reader, rva + (i - origIndex)));
}
}
/**
* {@return the virtual address}
*/
public int getVirualAddress() {
return virtualAddress;
}
/**
* {@return the size of the block}
*/
public int getSizeOfBlock() {
return sizeOfBlock;
}
/**
* {@return the {@link List} of {@link ImageArm64XDynamicRelocation}s}
*/
public List<ImageArm64XDynamicRelocation> getRelocs() {
return relocs;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
ReferenceManager refMgr = program.getReferenceManager();
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (ImageArm64XDynamicRelocation reloc : relocs) {
reloc.markup(program, isBinary, monitor, log, ntHeader);
int pageRelativeOffset = reloc.getPageRelativeOffset();
if (pageRelativeOffset != 0) {
refMgr.addMemoryReference(addr, imageBase.add(virtualAddress + pageRelativeOffset),
RefType.DATA, SourceType.IMPORTED, 0);
}
addr = addr.add(reloc.toDataType().getLength() + reloc.getData().length);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_ARM64X", 0);
struct.add(IBO32, "VirtualAddress", null);
struct.add(DWORD, "SizeOfBlock", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,132 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_ARM64X_DYNAMIC_RELOCATION} structure
*/
public class ImageArm64XDynamicRelocation implements StructConverter, PeMarkupable {
private int pageRelativeOffset;
private int type;
private int meta;
private byte[] data;
private long rva;
/**
* Creates a new {@link ImageArm64XDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageArm64XDynamicRelocation(BinaryReader reader, long rva) throws IOException {
this.rva = rva;
int bitfield = reader.readNextUnsignedShort();
if (bitfield == 0) {
data = new byte[0];
return;
}
pageRelativeOffset = bitfield & 0xfff;
type = (bitfield >> 12) & 0x3;
meta = (bitfield >> 14) & 0x3;
int size = switch (type) {
case 0 -> 0; // zero fill
case 1 -> 1 << meta; // assign value
case 2 -> 2; // add (or sub) delta
default -> 2;
};
data = reader.readNextByteArray(size);
}
/**
* {@return the page relative offset}
*/
public int getPageRelativeOffset() {
return pageRelativeOffset;
}
/**
* {@return the type}
*/
public int getType() {
return type;
}
/**
* {@return the data}
*/
public byte[] getData() {
return data;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
DataType dataDt = switch (data.length) {
case 1 -> BYTE;
case 2 -> WORD;
case 4 -> DWORD;
case 8 -> QWORD;
default -> null;
};
if (dataDt != null) {
PeUtils.createData(program, addr, dataDt, log);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("IMAGE_ARM64X_DYNAMIC_RELOCATION", 0);
struct.setPackingEnabled(true);
try {
struct.addBitField(WORD, 12, "PageRelativeOffset", null);
struct.addBitField(WORD, 2, "Type", null);
struct.addBitField(WORD, 2, "Meta", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,97 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_BDD_DYNAMIC_RELOCATION} structure
*/
public class ImageBddDynamicRelocation implements StructConverter, PeMarkupable {
private int left;
private int right;
private int value;
private long rva;
/**
* Creates a new {@link ImageBddInfo}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageBddDynamicRelocation(BinaryReader reader, long rva) throws IOException {
this.rva = rva;
left = reader.readNextUnsignedShort();
right = reader.readNextUnsignedShort();
value = reader.readNextInt();
}
/**
* {@return the index of the FALSE edge in the BDD array}
*/
public int getLeft() {
return left;
}
/**
* {@return the index of the TRUE edge in the BDD array}
*/
public int getRight() {
return right;
}
/**
* {@return either the feature number or index in RVAs array}
*/
public int getValue() {
return value;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_BDD_DYNAMIC_RELOCATION", 0);
struct.add(WORD, "Left", "Index of FALSE edge in BDD array");
struct.add(WORD, "Right", "Index of TRUE edge in BDD array");
struct.add(DWORD, "Value", "Either FeatureNumber or Index into RVAs array");
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,101 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_BDD_INFO} structure
*/
public class ImageBddInfo implements StructConverter, PeMarkupable {
private int version;
private int bddSize;
private long rva;
private List<ImageBddDynamicRelocation> bddNodes = new ArrayList<>();
/**
* Creates a new {@link ImageBddInfo}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageBddInfo(BinaryReader reader, long rva) throws IOException {
this.rva = rva;
long origIndex = reader.getPointerIndex();
version = reader.readNextInt();
bddSize = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + bddSize; i = reader.getPointerIndex()) {
bddNodes.add(new ImageBddDynamicRelocation(reader,
rva + (reader.getPointerIndex() - origIndex)));
}
}
/**
* {@return the BDD version}
*/
public int getVersion() {
return version;
}
/**
* {@return the BDD size}
*/
public int getBddSize() {
return bddSize;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
for (ImageBddDynamicRelocation node : bddNodes) {
node.markup(program, isBinary, monitor, log, ntHeader);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_BDD_INFO", 0);
struct.add(DWORD, "Version", "decides the semantics of serialzed BDD");
struct.add(DWORD, "BDDSize", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,116 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_DYNAMIC_RELOCATION} structure
*/
public class ImageDynamicRelocation implements StructConverter, PeMarkupable {
private DvrtType symbol;
private int baseRelocSize;
private long rva;
private List<AbstractImageDynamicRelocationHeader> headers = new ArrayList<>();
/**
* Creates a new {@link ImageDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageDynamicRelocation(BinaryReader reader, long rva) throws IOException {
this.rva = rva;
long origIndex = reader.getPointerIndex();
symbol = reader.readNext(DvrtType::type);
baseRelocSize = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + baseRelocSize; i = reader.getPointerIndex()) {
long newRva = rva + (i - origIndex);
headers.add(switch (symbol) {
case IMAGE_DYNAMIC_RELOCATION_IMPORT_CONTROL_TRANSFER -> new ImageImportControlTransfer(
reader, newRva);
case IMAGE_DYNAMIC_RELOCATION_INDIR_CONTROL_TRANSFER -> new ImageIndirControlTransfer(
reader, newRva);
case IMAGE_DYNAMIC_RELOCATION_SWITCHABLE_BRANCH -> new ImageSwitchtableBranch(
reader, newRva);
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);
default -> new ImageUnsupportedRelocationHeader(reader, newRva, baseRelocSize);
});
}
}
/**
* {@return the relocation "symbol", which is really a {@link DvrtType type}
*/
public DvrtType getSymbol() {
return symbol;
}
/**
* {@return the size in bytes of the relocation}
*/
public int getBaseRelocSize() {
return baseRelocSize;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Listing listing = program.getListing();
Address imageBase = program.getImageBase();
Address start = imageBase.add(rva);
PeUtils.createData(program, start, toDataType(), log);
for (AbstractImageDynamicRelocationHeader header : headers) {
header.markup(program, isBinary, monitor, log, ntHeader);
}
listing.setComment(start, CommentType.PLATE,
symbol != null ? symbol.name() : "IMAGE_DYNAMIC_RELOCATION_<UNKNOWN>");
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_DYNAMIC_RELOCATION", 0);
struct.add(symbol != null ? symbol.toDataType() : QWORD, "Symbol", null);
struct.add(DWORD, "BaseRelocSize", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,98 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_DYNAMIC_RELOCATION_TABLE} structure
*/
public class ImageDynamicRelocationTable implements StructConverter, PeMarkupable {
private int version;
private int size;
private long rva;
private List<ImageDynamicRelocation> relocations = new ArrayList<>();
/**
* Creates a new {@link ImageDynamicRelocationTable}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageDynamicRelocationTable(BinaryReader reader, long rva) throws IOException {
this.rva = rva;
long origIndex = reader.getPointerIndex();
version = reader.readNextInt();
size = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + size; i = reader.getPointerIndex()) {
relocations.add(new ImageDynamicRelocation(reader, rva + (i - origIndex)));
}
}
/**
* {@return the dynamic value relocation table version}
*/
public int getVersion() {
return version;
}
/**
* {@return the size in bytes of the dynamic value relocation table}
*/
public int getSize() {
return size;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
PeUtils.createData(program, imageBase.add(rva), toDataType(), log);
for (ImageDynamicRelocation reloc : relocations) {
reloc.markup(program, isBinary, monitor, log, ntHeader);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_DYNAMIC_RELOCATION_TABLE", 0);
struct.add(DWORD, "Version", null);
struct.add(DWORD, "Size", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,138 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION} structure
*/
public class ImageFunctionOverrideDynamicRelocation implements StructConverter, PeMarkupable {
private int originalRva;
private int bddOffset;
private int rvaSize;
private int baseRelocSize;
private long rva;
private int[] rvas;
private List<BaseRelocation> baseRelocs = new ArrayList<>();
/**
* Creates a new {@link ImageFunctionOverrideDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageFunctionOverrideDynamicRelocation(BinaryReader reader, long rva)
throws IOException {
this.rva = rva;
originalRva = reader.readNextInt();
bddOffset = reader.readNextInt();
rvaSize = reader.readNextInt();
baseRelocSize = reader.readNextInt();
rvas = reader.readNextIntArray(rvaSize / 4);
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + baseRelocSize; i = reader.getPointerIndex()) {
baseRelocs.add(new BaseRelocation(reader));
}
}
/**
* {@return the relative virtual address of the original function}
*/
public int getOriginalRva() {
return originalRva;
}
/**
* {@return the offset into the BDD region}
*/
public int getBddOffset() {
return bddOffset;
}
/**
* {@return the size in bytes taken by relative virtual addresses}
*/
public int getRvaSize() {
return rvaSize;
}
/**
* {@return the size in bytes taken by BaseRelocs}
*/
public int getBaseRelocSize() {
return baseRelocSize;
}
/**
* {@return the {@link List} of {@link BaseRelocation}s}
*/
public List<BaseRelocation> getBaseRelocs() {
return baseRelocs;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (int i = 0; i < rvas.length; i++) {
PeUtils.createData(program, addr, IBO32, log);
addr = addr.add(IBO32.getLength());
}
for (BaseRelocation baseReloc : baseRelocs) {
baseReloc.markup(program, addr, isBinary, monitor, log, ntHeader);
addr = addr.add(baseReloc.getSizeOfBlock());
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION", 0);
struct.add(IBO32, "OriginalRva", "RVA of original function");
struct.add(DWORD, "BDDOffset", "Offset into the BDD region");
struct.add(DWORD, "RvaSize",
"Size in bytes taken by RVAs. Must be multiple of sizeof(DWORD).");
struct.add(DWORD, "BaseRelocSize", "Size in bytes taken by BaseRelocs");
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,116 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_FUNCTION_OVERRIDE_HEADER} structure
*/
public class ImageFunctionOverrideHeader extends AbstractImageDynamicRelocationHeader {
private int funcOverrideSize;
private List<ImageFunctionOverrideDynamicRelocation> funcOverrideInfos = new ArrayList<>();
private List<ImageBddInfo> bddInfos = new ArrayList<>();
/**
* Creates a new {@link ImageFunctionOverrideHeader}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @param dvrtEntrySize The size in bytes of this header's
* {@link ImageDynamicRelocation DVRT entry}
* @throws IOException if there was an IO-related error
*/
public ImageFunctionOverrideHeader(BinaryReader reader, long rva, int dvrtEntrySize)
throws IOException {
super(rva);
long origIndex = reader.getPointerIndex();
funcOverrideSize = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + funcOverrideSize; i = reader.getPointerIndex()) {
funcOverrideInfos
.add(new ImageFunctionOverrideDynamicRelocation(reader, rva + (i - origIndex)));
}
int bddSize = dvrtEntrySize - 4 - funcOverrideSize;
startIndex = reader.getPointerIndex();
for (long i = startIndex; i < startIndex + bddSize; i = reader.getPointerIndex()) {
bddInfos.add(new ImageBddInfo(reader, rva + (i - origIndex)));
}
}
/**
* {@return the function override size}
*/
public int getFuncOverrideSize() {
return funcOverrideSize;
}
/**
* {@return the {@link List} of {@link ImageFunctionOverrideDynamicRelocation}s
*/
public List<ImageFunctionOverrideDynamicRelocation> getFuncOverrideInfo() {
return funcOverrideInfos;
}
/**
* {@return the {@link List} of {@link ImageBddInfo}s}
*/
public List<ImageBddInfo> getBddInfo() {
return bddInfos;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
for (ImageFunctionOverrideDynamicRelocation info : funcOverrideInfos) {
info.markup(program, isBinary, monitor, log, ntHeader);
}
for (ImageBddInfo info : bddInfos) {
info.markup(program, isBinary, monitor, log, ntHeader);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_FUNCTION_OVERRIDE_HEADER", 0);
struct.add(DWORD, "FuncOverrideSize", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,115 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Contains a list of {@link ImageImportControlTransferDynamicRelocation}s
*/
public class ImageImportControlTransfer extends AbstractImageDynamicRelocationHeader {
private int virtualAddress;
private int sizeOfBlock;
private List<ImageImportControlTransferDynamicRelocation> relocs = new ArrayList<>();
/**
* Creates a new {@link ImageIndirControlTransfer}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageImportControlTransfer(BinaryReader reader, long rva) throws IOException {
super(rva);
long origIndex = reader.getPointerIndex();
virtualAddress = reader.readNextInt();
sizeOfBlock = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < origIndex + sizeOfBlock; i = reader.getPointerIndex()) {
relocs.add(
new ImageImportControlTransferDynamicRelocation(reader, rva + (i - origIndex)));
}
}
/**
* {@return the virtual address}
*/
public int getVirualAddress() {
return virtualAddress;
}
/**
* {@return the size of the block}
*/
public int getSizeOfBlock() {
return sizeOfBlock;
}
/**
* {@return the {@link List} of {@link ImageImportControlTransferDynamicRelocation}s}
*/
public List<ImageImportControlTransferDynamicRelocation> getRelocs() {
return relocs;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
ReferenceManager refMgr = program.getReferenceManager();
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (ImageImportControlTransferDynamicRelocation reloc : relocs) {
reloc.markup(program, isBinary, monitor, log, ntHeader);
int pageRelativeOffset = reloc.getPageRelativeOffset();
if (pageRelativeOffset != 0) {
refMgr.addMemoryReference(addr, imageBase.add(virtualAddress + pageRelativeOffset),
RefType.DATA, SourceType.IMPORTED, 0);
}
addr = addr.add(reloc.toDataType().getLength());
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_IMPORT_CONTROL_TRANSFER", 0);
struct.add(IBO32, "VirtualAddress", null);
struct.add(DWORD, "SizeOfBlock", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,109 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION} structure
*/
public class ImageImportControlTransferDynamicRelocation implements StructConverter, PeMarkupable {
private int pageRelativeOffset;
private boolean indirectCall;
private int iatIndex;
// TODO: IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION has a different bitfield
private long rva;
/**
* Creates a new {@link ImageImportControlTransferDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* {@link ImageDynamicRelocation DVRT entry}
* @throws IOException if there was an IO-related error
*/
public ImageImportControlTransferDynamicRelocation(BinaryReader reader, long rva)
throws IOException {
this.rva = rva;
int bitfield = reader.readNextInt();
pageRelativeOffset = bitfield & 0xfff;
indirectCall = ((bitfield >> 12) & 0x1) != 0;
iatIndex = (bitfield >> 13) & 0x7ffff;
}
/**
* {@return the page relative offset}
*/
public int getPageRelativeOffset() {
return pageRelativeOffset;
}
/**
* {@return whether or not it's an indirect call}
*/
public boolean isIndirectCall() {
return indirectCall;
}
/**
* {@return the IAT index}
*/
public int getIatIndex() {
return iatIndex;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION", 0);
struct.setPackingEnabled(true);
try {
struct.addBitField(DWORD, 12, "PageRelativeOffset", null);
struct.addBitField(DWORD, 1, "IndirectCall", null);
struct.addBitField(DWORD, 19, "IATIndex", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,115 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Contains a list of {@link ImageIndirControlTransferDynamicRelocation}s
*/
public class ImageIndirControlTransfer extends AbstractImageDynamicRelocationHeader {
private int virtualAddress;
private int sizeOfBlock;
private List<ImageIndirControlTransferDynamicRelocation> relocs = new ArrayList<>();
/**
* Creates a new {@link ImageIndirControlTransfer}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageIndirControlTransfer(BinaryReader reader, long rva) throws IOException {
super(rva);
long origIndex = reader.getPointerIndex();
virtualAddress = reader.readNextInt();
sizeOfBlock = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < origIndex + sizeOfBlock; i = reader.getPointerIndex()) {
relocs.add(
new ImageIndirControlTransferDynamicRelocation(reader, rva + (i - origIndex)));
}
}
/**
* {@return the virtual address}
*/
public int getVirualAddress() {
return virtualAddress;
}
/**
* {@return the size of the block}
*/
public int getSizeOfBlock() {
return sizeOfBlock;
}
/**
* {@return the {@link List} of {@link ImageIndirControlTransferDynamicRelocation}s}
*/
public List<ImageIndirControlTransferDynamicRelocation> getRelocs() {
return relocs;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
ReferenceManager refMgr = program.getReferenceManager();
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (ImageIndirControlTransferDynamicRelocation reloc : relocs) {
reloc.markup(program, isBinary, monitor, log, ntHeader);
int pageRelativeOffset = reloc.getPageRelativeOffset();
if (pageRelativeOffset != 0) {
refMgr.addMemoryReference(addr, imageBase.add(virtualAddress + pageRelativeOffset),
RefType.DATA, SourceType.IMPORTED, 0);
}
addr = addr.add(reloc.toDataType().getLength());
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_INDIR_CONTROL_TRANSFER", 0);
struct.add(IBO32, "VirtualAddress", null);
struct.add(DWORD, "SizeOfBlock", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,127 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION} structure
*/
public class ImageIndirControlTransferDynamicRelocation implements StructConverter, PeMarkupable {
private int pageRelativeOffset;
private boolean indirectCall;
private boolean rexWPrefix;
private boolean cfgCheck;
private int reserved;
private long rva;
/**
* Creates a new {@link ImageIndirControlTransferDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageIndirControlTransferDynamicRelocation(BinaryReader reader, long rva)
throws IOException {
this.rva = rva;
int bitfield = reader.readNextUnsignedShort();
pageRelativeOffset = bitfield & 0xfff;
indirectCall = ((bitfield >> 12) & 0x1) != 0;
rexWPrefix = ((bitfield >> 13) & 0x1) != 0;
cfgCheck = ((bitfield >> 14) & 0x1) != 0;
reserved = (bitfield >> 15) & 0x1;
}
/**
* {@return the page relative offset}
*/
public int getPageRelativeOffset() {
return pageRelativeOffset;
}
/**
* {@return whether or not it's an indirect call}
*/
public boolean isIndirectCall() {
return indirectCall;
}
/**
* {@return whether or not there is a rexw prefix}
*/
public boolean isRexWPrefix() {
return rexWPrefix;
}
/**
* {@return whether or not it's a CFG check}
*/
public boolean isCfgCheck() {
return cfgCheck;
}
/**
* {@return the reserved bit}
*/
public int getReserved() {
return reserved;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION", 0);
struct.setPackingEnabled(true);
try {
struct.addBitField(WORD, 12, "PageRelativeOffset", null);
struct.addBitField(WORD, 1, "IndirectCall", null);
struct.addBitField(WORD, 1, "RexWPrefix", null);
struct.addBitField(WORD, 1, "CfgCheck", null);
struct.addBitField(WORD, 1, "Reserved", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,114 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Contains a list of {@link ImageSwitchtableBranchDynamicRelocation}s
*/
public class ImageSwitchtableBranch extends AbstractImageDynamicRelocationHeader {
private int virtualAddress;
private int sizeOfBlock;
private List<ImageSwitchtableBranchDynamicRelocation> relocs = new ArrayList<>();
/**
* Creates a new {@link ImageSwitchtableBranch}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @throws IOException if there was an IO-related error
*/
public ImageSwitchtableBranch(BinaryReader reader, long rva) throws IOException {
super(rva);
long origIndex = reader.getPointerIndex();
virtualAddress = reader.readNextInt();
sizeOfBlock = reader.readNextInt();
long startIndex = reader.getPointerIndex();
for (long i = startIndex; i < origIndex + sizeOfBlock; i = reader.getPointerIndex()) {
relocs.add(new ImageSwitchtableBranchDynamicRelocation(reader, rva + (i - origIndex)));
}
}
/**
* {@return the virtual address}
*/
public int getVirualAddress() {
return virtualAddress;
}
/**
* {@return the size of the block}
*/
public int getSizeOfBlock() {
return sizeOfBlock;
}
/**
* {@return the {@link List} of {@link ImageIndirControlTransferDynamicRelocation}s}
*/
public List<ImageSwitchtableBranchDynamicRelocation> getRelocs() {
return relocs;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
ReferenceManager refMgr = program.getReferenceManager();
Address imageBase = program.getImageBase();
DataType dt = toDataType();
Address addr = imageBase.add(rva);
PeUtils.createData(program, addr, dt, log);
addr = addr.add(dt.getLength());
for (ImageSwitchtableBranchDynamicRelocation reloc : relocs) {
reloc.markup(program, isBinary, monitor, log, ntHeader);
int pageRelativeOffset = reloc.getPageRelativeOffset();
if (pageRelativeOffset != 0) {
refMgr.addMemoryReference(addr, imageBase.add(virtualAddress + pageRelativeOffset),
RefType.DATA, SourceType.IMPORTED, 0);
}
addr = addr.add(reloc.toDataType().getLength());
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("IMAGE_SWITCHTABLE_BRANCH", 0);
struct.add(IBO32, "VirtualAddress", null);
struct.add(DWORD, "SizeOfBlock", null);
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,97 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a {@code IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION} structure
*/
public class ImageSwitchtableBranchDynamicRelocation implements StructConverter, PeMarkupable {
private int pageRelativeOffset;
private int registerNumber;
private long rva;
/**
* Creates a new {@link ImageSwitchtableBranchDynamicRelocation}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* {@link ImageDynamicRelocation DVRT entry}
* @throws IOException if there was an IO-related error
*/
public ImageSwitchtableBranchDynamicRelocation(BinaryReader reader, long rva)
throws IOException {
this.rva = rva;
int bitfield = reader.readNextUnsignedShort();
pageRelativeOffset = bitfield & 0xfff;
registerNumber = (bitfield >> 12) & 0xf;
}
/**
* {@return the page relative offset}
*/
public int getPageRelativeOffset() {
return pageRelativeOffset;
}
/**
* {@return the register number}
*/
public int getRegisterNumber() {
return registerNumber;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
DataType dt = toDataType();
PeUtils.createData(program, imageBase.add(rva), dt, log);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION", 0);
struct.setPackingEnabled(true);
try {
struct.addBitField(WORD, 12, "PageRelativeOffset", null);
struct.addBitField(WORD, 4, "RegisterNumber", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.setCategoryPath(new CategoryPath("/PE"));
return struct;
}
}
@@ -0,0 +1,73 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.pe.dvrt;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.pe.NTHeader;
import ghidra.app.util.bin.format.pe.PeUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents an unsupported dynamic value relocation header
*/
public class ImageUnsupportedRelocationHeader extends AbstractImageDynamicRelocationHeader {
private byte[] data;
/**
* Creates a new {@link ImageUnsupportedRelocationHeader}
*
* @param reader A {@link BinaryReader} that points to the start of the structure
* @param rva The relative virtual address of the structure
* @param size The size in bytes of this header's data
* @throws IOException if there was an IO-related error
*/
public ImageUnsupportedRelocationHeader(BinaryReader reader, long rva, int size)
throws IOException {
super(rva);
data = reader.readNextByteArray(size);
}
/**
* {@return the data associated with the unknown header}
*/
public byte[] getData() {
return data;
}
@Override
public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException,
IOException, MemoryAccessException {
Address imageBase = program.getImageBase();
PeUtils.createData(program, imageBase.add(rva), toDataType(), log);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return new ArrayDataType(BYTE, data.length, 1);
}
}