80 lines
3.7 KiB
Java
80 lines
3.7 KiB
Java
// Decode the track-row builder: the function that maps a djmdContent record into
|
|
// the on-disk DeviceSQL row (offset 0x02 index_shift, 0x14 u4 hash, 0x18/0x1a u2).
|
|
// Decompiles FUN_141c04be0 (AnalysisDataPath/SearchStr/MasterContentID mapper) and
|
|
// FUN_141ae4860 (djmdContent), plus scans for code referencing the constant
|
|
// 0x21b4a7ab / 0xa7ab and for `<<5` row-index assignment.
|
|
// Output -> ~/ghidra_proj/decrow.txt
|
|
import java.io.PrintWriter;
|
|
import java.util.*;
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.app.decompiler.*;
|
|
import ghidra.program.model.address.*;
|
|
import ghidra.program.model.listing.*;
|
|
import ghidra.program.model.scalar.Scalar;
|
|
import ghidra.program.model.lang.OperandType;
|
|
|
|
public class DecRow extends GhidraScript {
|
|
PrintWriter out;
|
|
DecompInterface di;
|
|
Set<String> done = new HashSet<>();
|
|
FunctionManager fm;
|
|
|
|
void dec(String a, String why) {
|
|
Function f = fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
|
|
if (f == null) { out.println("// no function at " + a + " (" + why + ")"); return; }
|
|
if (!done.add(f.getEntryPoint().toString())) return;
|
|
out.println("\n//===== " + f.getName() + " @ " + f.getEntryPoint() + " [" + why + "] =====");
|
|
DecompileResults r = di.decompileFunction(f, 90, monitor);
|
|
out.println(r != null && r.decompileCompleted() ? r.getDecompiledFunction().getC() : "// decompile failed");
|
|
}
|
|
|
|
@Override public void run() throws Exception {
|
|
out = new PrintWriter("/home/ntr/ghidra_proj/decrow.txt");
|
|
di = new DecompInterface(); di.openProgram(currentProgram);
|
|
fm = currentProgram.getFunctionManager();
|
|
|
|
dec("0x141c04be0", "AnalysisDataPath/SearchStr/MasterContentID mapper");
|
|
dec("0x141c07230", "SearchStr 2");
|
|
dec("0x141c076d0", "SearchStr 3");
|
|
dec("0x141ae4860", "djmdContent xrefs");
|
|
|
|
// Scan all instructions for the per-export constants used in 0x18/0x1a
|
|
// (0xa7ab=42923, 0x21b4=8628, combined u4 0x21b4a7ab=565353387) and for
|
|
// an immediate 0x20 / shift-by-5 pattern that would build index_shift.
|
|
long[] consts = {0xa7abL, 0x21b4L, 0x21b4a7abL, 0xa7ab21b4L};
|
|
Set<String> hitFns = new LinkedHashSet<>();
|
|
Listing lst = currentProgram.getListing();
|
|
InstructionIterator it = lst.getInstructions(true);
|
|
int scanned = 0;
|
|
while (it.hasNext() && !monitor.isCancelled()) {
|
|
Instruction ins = it.next();
|
|
scanned++;
|
|
for (int op = 0; op < ins.getNumOperands(); op++) {
|
|
Object[] objs = ins.getOpObjects(op);
|
|
for (Object o : objs) {
|
|
if (o instanceof Scalar) {
|
|
long v = ((Scalar) o).getUnsignedValue();
|
|
for (long c : consts) {
|
|
if (v == c) {
|
|
Function f = fm.getFunctionContaining(ins.getAddress());
|
|
String tag = "const 0x" + Long.toHexString(c) + " @" + ins.getAddress()
|
|
+ " in " + (f != null ? f.getName() + "@" + f.getEntryPoint() : "?")
|
|
+ " : " + ins.toString();
|
|
out.println("// SCAN " + tag);
|
|
if (f != null) hitFns.add(f.getEntryPoint().toString() + "|const0x" + Long.toHexString(c));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out.println("// scanned " + scanned + " instructions");
|
|
for (String h : hitFns) {
|
|
String[] parts = h.split("\\|");
|
|
dec("0x" + parts[0], parts[1]);
|
|
}
|
|
out.flush(); out.close();
|
|
println("wrote decrow.txt");
|
|
}
|
|
}
|