mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-24 13:21:22 +08:00
GP-6502: The PE Dynamic Value Relocation Table (DVRT) is now parsed and
marked up
This commit is contained in:
+98
-23
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-19
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+52
-51
@@ -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);
|
||||
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
+114
@@ -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;
|
||||
}
|
||||
}
|
||||
+132
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+97
@@ -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;
|
||||
}
|
||||
}
|
||||
+101
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+116
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+98
@@ -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;
|
||||
}
|
||||
}
|
||||
+138
@@ -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;
|
||||
}
|
||||
}
|
||||
+116
@@ -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;
|
||||
}
|
||||
}
|
||||
+115
@@ -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;
|
||||
}
|
||||
}
|
||||
+109
@@ -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;
|
||||
}
|
||||
}
|
||||
+115
@@ -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;
|
||||
}
|
||||
}
|
||||
+127
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+114
@@ -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;
|
||||
}
|
||||
}
|
||||
+97
@@ -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;
|
||||
}
|
||||
}
|
||||
+73
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user