This commit is contained in:
Guus Waals 2025-05-30 14:36:39 +08:00
parent faf2e134f2
commit f1b346fb0e
1 changed files with 71 additions and 63 deletions

View File

@ -10,17 +10,21 @@ import ghidra.program.model.symbol.Reference;
import java.util.*; import java.util.*;
import java.io.*; import java.io.*;
import re3lib.RemanConfig; import re3lib.RemanConfig;
import ghidra.util.task.TaskMonitor;
public class FindRelocations extends GhidraScript { public class FindRelocations extends GhidraScript {
private Set<Address> foundRelocations = new HashSet<>(); private Set<Address> foundRelocations = new HashSet<>();
private PrintWriter outputFile; private PrintWriter outputFile;
long addrMin, addrMax;
@Override @Override
public void run() throws Exception { public void run() throws Exception {
RemanConfig.INSTANCE = new RemanConfig(this); RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories(); RemanConfig.INSTANCE.createDirectories();
addrMin = RemanConfig.INSTANCE.staticMemoryBlockStart.getOffset();
addrMax = RemanConfig.INSTANCE.staticMemoryBlockEnd.getOffset();
// Create output file for relocations // Create output file for relocations
File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.txt"); File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.txt");
outputFile = new PrintWriter(new FileWriter(relocFile)); outputFile = new PrintWriter(new FileWriter(relocFile));
@ -111,12 +115,12 @@ public class FindRelocations extends GhidraScript {
private boolean isRelocatableInstruction(String mnemonic) { private boolean isRelocatableInstruction(String mnemonic) {
// Instructions that commonly use absolute addresses // Instructions that commonly use absolute addresses
return mnemonic.equals("mov") || mnemonic.equals("lea") || return mnemonic.equals("mov") || mnemonic.equals("lea") ||
mnemonic.equals("call") || mnemonic.equals("jmp") || mnemonic.equals("call") || mnemonic.equals("jmp") ||
mnemonic.equals("push") || mnemonic.equals("cmp") || mnemonic.equals("push") || mnemonic.equals("cmp") ||
mnemonic.equals("test") || mnemonic.equals("add") || mnemonic.equals("test") || mnemonic.equals("add") ||
mnemonic.equals("sub") || mnemonic.equals("and") || mnemonic.equals("sub") || mnemonic.equals("and") ||
mnemonic.equals("or") || mnemonic.equals("xor") || mnemonic.equals("or") || mnemonic.equals("xor") ||
mnemonic.startsWith("j"); // conditional jumps mnemonic.startsWith("j"); // conditional jumps
} }
private void analyzeOperand(Instruction instruction, int opIndex) { private void analyzeOperand(Instruction instruction, int opIndex) {
@ -127,7 +131,7 @@ public class FindRelocations extends GhidraScript {
Address addr = (Address) obj; Address addr = (Address) obj;
if (isInMainMemorySpace(addr)) { if (isInMainMemorySpace(addr)) {
recordRelocation(instruction.getAddress(), addr, recordRelocation(instruction.getAddress(), addr,
instruction.getMnemonicString(), "operand_" + opIndex); instruction.getMnemonicString(), "operand_" + opIndex);
} }
} else if (obj instanceof Scalar) { } else if (obj instanceof Scalar) {
Scalar scalar = (Scalar) obj; Scalar scalar = (Scalar) obj;
@ -138,7 +142,7 @@ public class FindRelocations extends GhidraScript {
Address addr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value); Address addr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value);
if (isInMainMemorySpace(addr)) { if (isInMainMemorySpace(addr)) {
recordRelocation(instruction.getAddress(), addr, recordRelocation(instruction.getAddress(), addr,
instruction.getMnemonicString(), "scalar_" + opIndex); instruction.getMnemonicString(), "scalar_" + opIndex);
} }
} catch (Exception e) { } catch (Exception e) {
// Invalid address, ignore // Invalid address, ignore
@ -170,7 +174,7 @@ public class FindRelocations extends GhidraScript {
long value = 0; long value = 0;
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
value |= ((long)(bytes[i] & 0xFF)) << (i * 8); value |= ((long) (bytes[i] & 0xFF)) << (i * 8);
} }
if (looksLikeAddress(value)) { if (looksLikeAddress(value)) {
@ -203,17 +207,19 @@ public class FindRelocations extends GhidraScript {
} }
private boolean isInMainMemorySpace(Address addr) { private boolean isInMainMemorySpace(Address addr) {
if (addr == null) return false; if (addr == null)
return false;
// Check if address is in a loaded memory block // Check if address is in a loaded memory block
return currentProgram.getMemory().contains(addr) && return currentProgram.getMemory().contains(addr) &&
!addr.getAddressSpace().isOverlaySpace(); !addr.getAddressSpace().isOverlaySpace();
} }
private boolean looksLikeAddress(long value) { private boolean looksLikeAddress(long value) {
// Heuristic: check if value is in reasonable address range // Heuristic: check if value is in reasonable address range
// Adjust these ranges based on your target architecture // Adjust these ranges based on your target architecture
return value >= 0x400000 && value <= 0x7FFFFFFF; // Typical executable range return value >= addrMin
&& value <= addrMax; // Typical executable range
} }
private boolean usesAbsoluteAddressing(Instruction instruction, Reference ref) { private boolean usesAbsoluteAddressing(Instruction instruction, Reference ref) {
@ -245,11 +251,11 @@ public class FindRelocations extends GhidraScript {
if (foundRelocations.add(toAddr)) { if (foundRelocations.add(toAddr)) {
String instructionBytes = getInstructionBytesString(fromAddr); String instructionBytes = getInstructionBytesString(fromAddr);
String line = String.format("0x%s -> 0x%s (%s) [%s] | %s", String line = String.format("0x%s -> 0x%s (%s) [%s] | %s",
fromAddr.toString(), fromAddr.toString(),
toAddr.toString(), toAddr.toString(),
instruction, instruction,
type, type,
instructionBytes); instructionBytes);
println(line); println(line);
outputFile.println(line); outputFile.println(line);
outputFile.flush(); outputFile.flush();
@ -263,7 +269,8 @@ public class FindRelocations extends GhidraScript {
byte[] bytes = instruction.getBytes(); byte[] bytes = instruction.getBytes();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
if (i > 0) sb.append(" "); if (i > 0)
sb.append(" ");
sb.append(String.format("%02x", bytes[i] & 0xFF)); sb.append(String.format("%02x", bytes[i] & 0xFF));
} }
return sb.toString(); return sb.toString();
@ -275,7 +282,8 @@ public class FindRelocations extends GhidraScript {
currentProgram.getMemory().getBytes(addr, bytes); currentProgram.getMemory().getBytes(addr, bytes);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
if (i > 0) sb.append(" "); if (i > 0)
sb.append(" ");
sb.append(String.format("%02x", bytes[i] & 0xFF)); sb.append(String.format("%02x", bytes[i] & 0xFF));
} }
return sb.toString(); return sb.toString();