79 lines
3.3 KiB
Java
79 lines
3.3 KiB
Java
// Hunt for the track-row builder / the per-track 8-byte hash (row offsets
|
|
// 0x14 u4, 0x18 u2, 0x1a u2) and index_shift (0x02). Decompiles the string-hash
|
|
// function formatForSearch + its callers, and dumps xrefs of track/content/
|
|
// search-related strings. Output -> ~/ghidra_proj/hash.txt
|
|
import java.io.PrintWriter;
|
|
import java.util.*;
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.app.decompiler.*;
|
|
import ghidra.program.model.listing.*;
|
|
import ghidra.program.model.symbol.*;
|
|
|
|
public class FindHash extends GhidraScript {
|
|
PrintWriter out;
|
|
DecompInterface di;
|
|
Set<String> done = new HashSet<>();
|
|
FunctionManager fm;
|
|
ReferenceManager rm;
|
|
|
|
void dec(Function f, String why) {
|
|
if (f == null) return;
|
|
if (!done.add(f.getEntryPoint().toString())) return;
|
|
out.println("\n//===== " + f.getName() + " @ " + f.getEntryPoint() + " [" + why + "] =====");
|
|
DecompileResults r = di.decompileFunction(f, 60, monitor);
|
|
out.println(r != null && r.decompileCompleted() ? r.getDecompiledFunction().getC() : "// decompile failed");
|
|
}
|
|
|
|
Function fn(String a) {
|
|
return fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
|
|
}
|
|
|
|
@Override
|
|
public void run() throws Exception {
|
|
out = new PrintWriter("/home/ntr/ghidra_proj/hash.txt");
|
|
di = new DecompInterface(); di.openProgram(currentProgram);
|
|
fm = currentProgram.getFunctionManager();
|
|
rm = currentProgram.getReferenceManager();
|
|
|
|
// 1. formatForSearch (string hash) + its callers
|
|
Function fmt = fn("0x141a1afc0");
|
|
dec(fmt, "formatForSearch");
|
|
if (fmt != null) {
|
|
int n = 0;
|
|
for (Reference ref : rm.getReferencesTo(fmt.getEntryPoint())) {
|
|
if (n++ >= 10) break;
|
|
dec(fm.getFunctionContaining(ref.getFromAddress()), "caller of formatForSearch");
|
|
}
|
|
}
|
|
|
|
// 2. strings that hint at the track/content row builder -> xref functions
|
|
String[] kw = {"djmdContent", "SearchStr", "formatForSearch", "AnalysisDataPath",
|
|
"ContentID", "rb_data_status", "rb_local", "dsqlInsert", "AddTrack"};
|
|
DataIterator dit = currentProgram.getListing().getDefinedData(true);
|
|
int shown = 0;
|
|
while (dit.hasNext() && !monitor.isCancelled()) {
|
|
Data d = dit.next();
|
|
if (d == null || !d.hasStringValue()) continue;
|
|
Object v = d.getValue();
|
|
if (!(v instanceof String)) continue;
|
|
String s = (String) v;
|
|
for (String k : kw) {
|
|
if (s.contains(k)) {
|
|
out.println("\n// STRING @" + d.getAddress() + " : " + s);
|
|
int n = 0;
|
|
for (Reference ref : rm.getReferencesTo(d.getAddress())) {
|
|
if (n++ >= 5) break;
|
|
Function c = fm.getFunctionContaining(ref.getFromAddress());
|
|
out.println("// xref in " + (c != null ? c.getName() + " @" + c.getEntryPoint() : ref.getFromAddress()));
|
|
}
|
|
shown++;
|
|
break;
|
|
}
|
|
}
|
|
if (shown >= 30) break;
|
|
}
|
|
out.flush(); out.close();
|
|
println("wrote hash.txt");
|
|
}
|
|
}
|