97 lines
3.2 KiB
Java
97 lines
3.2 KiB
Java
// GhidraScript: FindStringXrefs.java
|
|
// Usage (headless):
|
|
// analyzeHeadless <projDir> <projName> -process <progName> \
|
|
// -scriptPath <path> -postScript FindStringXrefs.java "<needle1>" ["<needle2>" ...]
|
|
//
|
|
// Prints the addresses where the ASCII needle is found (optionally with NUL terminator)
|
|
// and lists the functions that reference the string address.
|
|
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.program.model.address.Address;
|
|
import ghidra.program.model.listing.Function;
|
|
import ghidra.program.model.mem.Memory;
|
|
import ghidra.program.model.symbol.Reference;
|
|
import ghidra.program.model.symbol.ReferenceIterator;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.LinkedHashSet;
|
|
|
|
public class FindStringXrefs extends GhidraScript {
|
|
@Override
|
|
public void run() throws Exception {
|
|
String[] args = getScriptArgs();
|
|
if (args == null || args.length == 0) {
|
|
printerr("FindStringXrefs: needs at least one ASCII needle arg");
|
|
return;
|
|
}
|
|
|
|
Memory mem = currentProgram.getMemory();
|
|
Address min = mem.getMinAddress();
|
|
Address max = mem.getMaxAddress();
|
|
|
|
for (String needle : args) {
|
|
if (needle == null) continue;
|
|
if (needle.isEmpty()) continue;
|
|
|
|
println("=== needle: " + needle + " ===");
|
|
|
|
byte[] pat0 = needle.getBytes(StandardCharsets.US_ASCII);
|
|
byte[] pat1 = new byte[pat0.length + 1];
|
|
System.arraycopy(pat0, 0, pat1, 0, pat0.length);
|
|
pat1[pat1.length - 1] = 0;
|
|
|
|
// First try NUL-terminated.
|
|
int hits = 0;
|
|
Address at = min;
|
|
while (true) {
|
|
Address found = mem.findBytes(at, max, pat1, null, true, monitor);
|
|
if (found == null) break;
|
|
hits++;
|
|
dumpHit(found);
|
|
at = found.add(1);
|
|
}
|
|
|
|
// If no NUL-terminated matches, fall back to raw bytes search.
|
|
if (hits == 0) {
|
|
at = min;
|
|
while (true) {
|
|
Address found = mem.findBytes(at, max, pat0, null, true, monitor);
|
|
if (found == null) break;
|
|
hits++;
|
|
dumpHit(found);
|
|
at = found.add(1);
|
|
}
|
|
}
|
|
|
|
if (hits == 0) {
|
|
println("(no hits)");
|
|
}
|
|
println("");
|
|
}
|
|
}
|
|
|
|
private void dumpHit(Address strAddr) {
|
|
println("hit @ " + strAddr);
|
|
|
|
LinkedHashSet<String> funcs = new LinkedHashSet<>();
|
|
ReferenceIterator it = currentProgram.getReferenceManager().getReferencesTo(strAddr);
|
|
int nref = 0;
|
|
while (it.hasNext()) {
|
|
Reference r = it.next();
|
|
nref++;
|
|
Function f = getFunctionContaining(r.getFromAddress());
|
|
if (f != null) {
|
|
funcs.add(f.getName() + " @ " + f.getEntryPoint());
|
|
} else {
|
|
funcs.add("(no func) from " + r.getFromAddress());
|
|
}
|
|
if (nref > 2000) break; // avoid pathological spam
|
|
}
|
|
println("refs: " + nref);
|
|
for (String s : funcs) {
|
|
println(" " + s);
|
|
if (funcs.size() > 200) break;
|
|
}
|
|
}
|
|
}
|