Wip relo finder
This commit is contained in:
parent
7613e37444
commit
faf2e134f2
|
@ -11,8 +11,6 @@ import java.util.*;
|
|||
import java.io.*;
|
||||
import re3lib.RemanConfig;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
|
||||
public class FindRelocations extends GhidraScript {
|
||||
private Set<Address> foundRelocations = new HashSet<>();
|
||||
|
@ -80,151 +78,34 @@ public class FindRelocations extends GhidraScript {
|
|||
private void analyzeInstruction(Instruction instruction) {
|
||||
String mnemonic = instruction.getMnemonicString().toLowerCase();
|
||||
|
||||
// Use pcode analysis for better accuracy
|
||||
// Check for instructions that commonly use absolute addresses
|
||||
if (isRelocatableInstruction(mnemonic)) {
|
||||
analyzeInstructionPcode(instruction);
|
||||
|
||||
// Still check operands for direct absolute addresses
|
||||
// Check operands for absolute addresses
|
||||
for (int i = 0; i < instruction.getNumOperands(); i++) {
|
||||
analyzeOperand(instruction, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeInstructionPcode(Instruction instruction) {
|
||||
try {
|
||||
PcodeOp[] pcode = instruction.getPcode();
|
||||
|
||||
for (PcodeOp op : pcode) {
|
||||
// Look for operations that use absolute addresses
|
||||
switch (op.getOpcode()) {
|
||||
case PcodeOp.LOAD:
|
||||
case PcodeOp.STORE:
|
||||
// Memory operations - check if using absolute address
|
||||
analyzeMemoryOperation(instruction, op);
|
||||
break;
|
||||
|
||||
case PcodeOp.CALL:
|
||||
case PcodeOp.CALLIND:
|
||||
// Call operations - check if target is absolute
|
||||
analyzeCallOperation(instruction, op);
|
||||
break;
|
||||
|
||||
case PcodeOp.BRANCH:
|
||||
case PcodeOp.BRANCHIND:
|
||||
// Branch operations - usually relative, but check indirect branches
|
||||
analyzeBranchOperation(instruction, op);
|
||||
break;
|
||||
|
||||
case PcodeOp.COPY:
|
||||
// Copy operations that move absolute addresses
|
||||
analyzeCopyOperation(instruction, op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Fallback to reference analysis if pcode fails
|
||||
analyzeReferences(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeMemoryOperation(Instruction instruction, PcodeOp op) {
|
||||
// LOAD/STORE operations with absolute addresses
|
||||
Varnode input = op.getInput(1); // Address input
|
||||
if (input != null && input.isConstant()) {
|
||||
long addr = input.getOffset();
|
||||
if (looksLikeAddress(addr)) {
|
||||
try {
|
||||
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(addr);
|
||||
if (isInMainMemorySpace(targetAddr)) {
|
||||
recordRelocation(instruction.getAddress(), targetAddr,
|
||||
instruction.getMnemonicString(), "memory_op");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Invalid address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeCallOperation(Instruction instruction, PcodeOp op) {
|
||||
// Only flag indirect calls or calls with absolute targets
|
||||
if (op.getOpcode() == PcodeOp.CALLIND) {
|
||||
// Indirect call - check if target address is absolute
|
||||
Varnode target = op.getInput(0);
|
||||
if (target != null && target.isConstant()) {
|
||||
long addr = target.getOffset();
|
||||
if (looksLikeAddress(addr)) {
|
||||
try {
|
||||
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(addr);
|
||||
if (isInMainMemorySpace(targetAddr)) {
|
||||
recordRelocation(instruction.getAddress(), targetAddr,
|
||||
instruction.getMnemonicString(), "indirect_call");
|
||||
// Check references from this instruction - but filter out relative references
|
||||
Reference[] refs = instruction.getReferencesFrom();
|
||||
for (Reference ref : refs) {
|
||||
// Skip relative references (jumps/calls with relative addressing)
|
||||
if (ref.getReferenceType().isCall() || ref.getReferenceType().isJump()) {
|
||||
// For jumps and calls, check if it's using absolute addressing
|
||||
if (usesAbsoluteAddressing(instruction, ref)) {
|
||||
Address toAddr = ref.getToAddress();
|
||||
if (isInMainMemorySpace(toAddr)) {
|
||||
recordRelocation(instruction.getAddress(), toAddr, mnemonic, "absolute_reference");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Invalid address
|
||||
}
|
||||
} else if (ref.getReferenceType().isData()) {
|
||||
// Data references are more likely to be absolute
|
||||
Address toAddr = ref.getToAddress();
|
||||
if (isInMainMemorySpace(toAddr)) {
|
||||
recordRelocation(instruction.getAddress(), toAddr, mnemonic, "data_reference");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Direct calls are usually relative, skip them
|
||||
}
|
||||
|
||||
private void analyzeBranchOperation(Instruction instruction, PcodeOp op) {
|
||||
// Only flag indirect branches (direct branches are relative)
|
||||
if (op.getOpcode() == PcodeOp.BRANCHIND) {
|
||||
Varnode target = op.getInput(0);
|
||||
if (target != null && target.isConstant()) {
|
||||
long addr = target.getOffset();
|
||||
if (looksLikeAddress(addr)) {
|
||||
try {
|
||||
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(addr);
|
||||
if (isInMainMemorySpace(targetAddr)) {
|
||||
recordRelocation(instruction.getAddress(), targetAddr,
|
||||
instruction.getMnemonicString(), "indirect_branch");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Invalid address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Direct branches (BRANCH) are relative, ignore them
|
||||
}
|
||||
|
||||
private void analyzeCopyOperation(Instruction instruction, PcodeOp op) {
|
||||
// COPY operations that load absolute addresses (like LEA or MOV immediate)
|
||||
Varnode input = op.getInput(0);
|
||||
if (input != null && input.isConstant()) {
|
||||
long addr = input.getOffset();
|
||||
if (looksLikeAddress(addr)) {
|
||||
try {
|
||||
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(addr);
|
||||
if (isInMainMemorySpace(targetAddr)) {
|
||||
recordRelocation(instruction.getAddress(), targetAddr,
|
||||
instruction.getMnemonicString(), "load_address");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Invalid address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeReferences(Instruction instruction) {
|
||||
// Fallback method - but be more selective
|
||||
Reference[] refs = instruction.getReferencesFrom();
|
||||
for (Reference ref : refs) {
|
||||
if (ref.getReferenceType().isData()) {
|
||||
// Data references are usually absolute
|
||||
Address toAddr = ref.getToAddress();
|
||||
if (isInMainMemorySpace(toAddr)) {
|
||||
recordRelocation(instruction.getAddress(), toAddr,
|
||||
instruction.getMnemonicString(), "data_reference");
|
||||
}
|
||||
}
|
||||
// Skip flow references (calls/jumps) as they're usually relative
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRelocatableInstruction(String mnemonic) {
|
||||
|
@ -335,16 +216,73 @@ public class FindRelocations extends GhidraScript {
|
|||
return value >= 0x400000 && value <= 0x7FFFFFFF; // Typical executable range
|
||||
}
|
||||
|
||||
private boolean usesAbsoluteAddressing(Instruction instruction, Reference ref) {
|
||||
// Check the instruction bytes to determine addressing mode
|
||||
String mnemonic = instruction.getMnemonicString().toLowerCase();
|
||||
|
||||
// For x86, most conditional jumps (JA, JE, JNE, etc.) use relative addressing
|
||||
if (mnemonic.startsWith("j") && !mnemonic.equals("jmp")) {
|
||||
return false; // Conditional jumps are typically relative
|
||||
}
|
||||
|
||||
// For JMP and CALL, check the operand representation
|
||||
for (int i = 0; i < instruction.getNumOperands(); i++) {
|
||||
String operandStr = instruction.getDefaultOperandRepresentation(i);
|
||||
// If operand shows as a direct address (not offset), it might be absolute
|
||||
// But we need to be more sophisticated here...
|
||||
|
||||
// Check if this is an indirect reference [address] which would be absolute
|
||||
if (operandStr.contains("[") && operandStr.contains("]")) {
|
||||
return true; // Indirect addressing typically uses absolute addresses
|
||||
}
|
||||
}
|
||||
|
||||
// For now, assume most jumps/calls are relative unless proven otherwise
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type) {
|
||||
if (foundRelocations.add(toAddr)) {
|
||||
String line = String.format("0x%s -> 0x%s (%s) [%s]",
|
||||
String instructionBytes = getInstructionBytesString(fromAddr);
|
||||
String line = String.format("0x%s -> 0x%s (%s) [%s] | %s",
|
||||
fromAddr.toString(),
|
||||
toAddr.toString(),
|
||||
instruction,
|
||||
type);
|
||||
type,
|
||||
instructionBytes);
|
||||
println(line);
|
||||
outputFile.println(line);
|
||||
outputFile.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private String getInstructionBytesString(Address addr) {
|
||||
try {
|
||||
Instruction instruction = currentProgram.getListing().getInstructionAt(addr);
|
||||
if (instruction != null) {
|
||||
byte[] bytes = instruction.getBytes();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (i > 0) sb.append(" ");
|
||||
sb.append(String.format("%02x", bytes[i] & 0xFF));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// If it's a data reference, try to get the bytes at that location
|
||||
try {
|
||||
byte[] bytes = new byte[4]; // Show 4 bytes for data
|
||||
currentProgram.getMemory().getBytes(addr, bytes);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (i > 0) sb.append(" ");
|
||||
sb.append(String.format("%02x", bytes[i] & 0xFF));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Exception ex) {
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue