Files
openroller/tools/ghidra_scripts/FindVirtualCallOffset.java
tsuki 831d96e562 Initial public source release
Split reusable rendering and format support into vectorail-core and vectorail-gc.
2026-08-02 17:05:27 +02:00

79 lines
3.1 KiB
Java

// GhidraScript: FindVirtualCallOffset.java
// Usage:
// analyzeHeadless <projDir> <projName> -process <progName> -noanalysis -readOnly \
// -scriptPath tools/ghidra_scripts -postScript FindVirtualCallOffset.java 0xc4 [minAddr] [maxAddr]
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.scalar.Scalar;
public class FindVirtualCallOffset extends GhidraScript {
private boolean hasScalar(Instruction ins, long want) {
for (int op = 0; op < ins.getNumOperands(); op++) {
for (Object obj : ins.getOpObjects(op)) {
if (obj instanceof Scalar) {
Scalar s = (Scalar)obj;
if (s.getUnsignedValue() == want || s.getSignedValue() == want) return true;
}
}
}
return false;
}
private boolean inRange(Address addr, Address min, Address max) {
if (min != null && addr.compareTo(min) < 0) return false;
if (max != null && addr.compareTo(max) > 0) return false;
return true;
}
private boolean followedByCall(Instruction ins) {
Instruction n = ins.getNext();
if (n != null && "CALL".equals(n.getMnemonicString())) return true;
n = n == null ? null : n.getNext();
return n != null && "CALL".equals(n.getMnemonicString());
}
@Override
public void run() throws Exception {
String[] args = getScriptArgs();
if (args == null || args.length == 0) {
printerr("FindVirtualCallOffset: needs vtable offset");
return;
}
long want = Long.decode(args[0]);
Address min = args.length > 1 ? toAddr(Long.decode(args[1])) : null;
Address max = args.length > 2 ? toAddr(Long.decode(args[2])) : null;
println("=== virtual call offset " + args[0] + " ===");
int hits = 0;
for (Instruction ins : currentProgram.getListing().getInstructions(true)) {
if (!inRange(ins.getAddress(), min, max)) continue;
if (!"MOV".equals(ins.getMnemonicString())) continue;
if (!hasScalar(ins, want)) continue;
if (!followedByCall(ins)) continue;
hits++;
Function f = getFunctionContaining(ins.getAddress());
String fs = f == null ? "(no func)" : f.getName() + " @ " + f.getEntryPoint();
println("");
println("HIT " + hits + " " + ins.getAddress() + " " + fs);
Instruction cur = ins;
for (int i = 0; i < 8; i++) {
Instruction prev = cur.getPrevious();
if (prev == null) break;
cur = prev;
}
for (int i = 0; i < 14 && cur != null; i++) {
String mark = cur.getAddress().equals(ins.getAddress()) ? "=>" : " ";
println(mark + " " + cur.getAddress() + " " + cur);
cur = cur.getNext();
}
if (monitor.isCancelled()) break;
}
println("hits: " + hits);
}
}