the downfall has begun

This commit is contained in:
Nathan Rashleigh committed 2026-06-09 18:46:25 +10:00
1 parent f71a2a3512
commit 9ccc3cea95
25 files changed
+4976 -109

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
// Decompile the export root FUN_14119d2d0 and selected callees, to find the
// per-track row-insert that sets index_shift (0x02) and the 0x14/0x18/0x1a blob.
// Also dump callees of FUN_14117be20 (rekordbox/export.pdb string xref).
// Output -> ~/ghidra_proj/decroot.txt
import java.io.PrintWriter;
import java.util.*;
import ghidra.app.script.GhidraScript;
import ghidra.app.decompiler.*;
import ghidra.program.model.listing.*;
public class DecRoot extends GhidraScript {
PrintWriter out; DecompInterface di; FunctionManager fm;
Set<String> done = new HashSet<>();
void dec(String a, String why) {
Function f = fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
if (f == null) { out.println("// no fn at " + a + " (" + why + ")"); return; }
if (!done.add(f.getEntryPoint().toString())) return;
out.println("\n//===== " + f.getName() + " @ " + f.getEntryPoint() + " [" + why + "] =====");
DecompileResults r = di.decompileFunction(f, 120, monitor);
out.println(r != null && r.decompileCompleted() ? r.getDecompiledFunction().getC() : "// decompile failed: "+(r!=null?r.getErrorMessage():"null"));
}
@Override public void run() throws Exception {
out = new PrintWriter("/home/ntr/ghidra_proj/decroot.txt");
di = new DecompInterface(); di.openProgram(currentProgram);
fm = currentProgram.getFunctionManager();
dec("0x14119d2d0", "export root (/.PIONEER/rekordbox/export.pdb)");
dec("0x14117be20", "rekordbox/export.pdb xref");
out.flush(); out.close();
println("wrote decroot.txt");
}
}
+79
View File
@@ -0,0 +1,79 @@
// 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");
}
}
+30
View File
@@ -0,0 +1,30 @@
// Decompile the prime index_shift candidate FUN_14232a86c (shl5 + mask 0x7ff) and
// a few neighboring DeviceSQL page-manager functions. Output -> ~/ghidra_proj/decshift.txt
import java.io.PrintWriter;
import java.util.*;
import ghidra.app.script.GhidraScript;
import ghidra.app.decompiler.*;
import ghidra.program.model.listing.*;
public class DecShift extends GhidraScript {
PrintWriter out; DecompInterface di; FunctionManager fm; Set<String> done=new HashSet<>();
void dec(String a, String why) {
Function f = fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
if (f == null) { out.println("// no fn at " + a + " (" + why + ")"); return; }
if (!done.add(f.getEntryPoint().toString())) return;
out.println("\n//===== " + f.getName() + " @ " + f.getEntryPoint() + " [" + why + "] =====");
DecompileResults r = di.decompileFunction(f, 120, 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/decshift.txt");
di = new DecompInterface(); di.openProgram(currentProgram);
fm = currentProgram.getFunctionManager();
dec("0x14232a86c", "shl5+mask7ff PRIME index_shift candidate");
// neighbors in DeviceSQL page-manager range
dec("0x1423e1550", "page-mgr neighbor");
dec("0x1423e12a0", "page-mgr neighbor");
out.flush(); out.close();
println("wrote decshift.txt");
}
}
+47
View File
@@ -0,0 +1,47 @@
// @flesniak documented track-row 0x18=u2 "always 19048" (0x4A68) and 0x1a=u2
// "always 30967" (0x78F7). Our AceMo export has 0xa7ab / 0x21b4 instead, and a
// const-scan found no 0xa7ab/0x21b4 immediates. So locate every reference to the
// documented defaults 0x4A68 and 0x78F7 (and combined 0x78F74A68 / 0x4A6878F7),
// decompile the containing functions, and report. This should reveal how 0x18/0x1a
// are produced (literal default vs computed). Output -> ~/ghidra_proj/find4a68.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.scalar.Scalar;
public class Find4A68 extends GhidraScript {
@Override public void run() throws Exception {
PrintWriter out = new PrintWriter("/home/ntr/ghidra_proj/find4a68.txt");
FunctionManager fm = currentProgram.getFunctionManager();
DecompInterface di = new DecompInterface(); di.openProgram(currentProgram);
long[] consts = {0x4A68L, 0x78F7L, 0x78F74A68L, 0x4A6878F7L, 19048L, 30967L};
Set<String> fns = new LinkedHashSet<>();
InstructionIterator it = currentProgram.getListing().getInstructions(true);
while (it.hasNext() && !monitor.isCancelled()) {
Instruction ins = it.next();
for (int op=0; op<ins.getNumOperands(); op++)
for (Object o : ins.getOpObjects(op))
if (o instanceof Scalar) {
long v=((Scalar)o).getUnsignedValue();
for (long c: consts) if (v==c) {
Function f=fm.getFunctionContaining(ins.getAddress());
out.println("// HIT 0x"+Long.toHexString(c)+" @"+ins.getAddress()
+" in "+(f!=null?f.getName()+"@"+f.getEntryPoint():"?")+" : "+ins.toString());
if (f!=null) fns.add(f.getEntryPoint().toString());
}
}
}
// also search defined data for the byte patterns
out.println("// --- decompiling containing functions ---");
for (String a: fns) {
Function f=fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
out.println("\n//===== "+f.getName()+" @ "+f.getEntryPoint()+" =====");
DecompileResults r=di.decompileFunction(f,90,monitor);
out.println(r!=null&&r.decompileCompleted()?r.getDecompiledFunction().getC():"// decompile failed");
}
out.flush(); out.close();
println("wrote find4a68.txt");
}
}
+44
View File
@@ -0,0 +1,44 @@
// Anchor the track-row builder via the track-row bitmask 0xc0700 (constant in
// every AceMo track row at offset 0x04) and the subtype/0x24 nearby. Find any
// instruction with immediate 0xc0700 and decompile the function. Output ->
// ~/ghidra_proj/findbitmask.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.scalar.Scalar;
public class FindBitmask extends GhidraScript {
@Override public void run() throws Exception {
PrintWriter out = new PrintWriter("/home/ntr/ghidra_proj/findbitmask.txt");
FunctionManager fm = currentProgram.getFunctionManager();
DecompInterface di = new DecompInterface(); di.openProgram(currentProgram);
long[] consts = {0xc0700L, 0x700L, 0xc07L};
Set<String> fns = new LinkedHashSet<>();
InstructionIterator it = currentProgram.getListing().getInstructions(true);
while (it.hasNext() && !monitor.isCancelled()) {
Instruction ins = it.next();
for (int op=0; op<ins.getNumOperands(); op++)
for (Object o : ins.getOpObjects(op))
if (o instanceof Scalar) {
long v=((Scalar)o).getUnsignedValue();
if (v==0xc0700L) {
Function f=fm.getFunctionContaining(ins.getAddress());
out.println("// HIT 0xc0700 @"+ins.getAddress()+" in "
+(f!=null?f.getName()+"@"+f.getEntryPoint():"?")+" : "+ins.toString());
if (f!=null) fns.add(f.getEntryPoint().toString());
}
}
}
out.println("// --- decompiling ---");
for (String a: fns) {
Function f=fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a));
out.println("\n//===== "+f.getName()+" @ "+f.getEntryPoint()+" =====");
DecompileResults r=di.decompileFunction(f,120,monitor);
out.println(r!=null&&r.decompileCompleted()?r.getDecompiledFunction().getC():"// fail");
}
out.flush(); out.close();
println("wrote findbitmask.txt");
}
}
+28
View File
@@ -0,0 +1,28 @@
// Confirm 0x78f74a68 / 0x4a68 / 0x78f7 is rekordbox's default opaque_seed by
// searching DEFINED DATA (not just instruction immediates) for the byte pattern
// 68 4a f7 78 (LE u4) and the two u2s, and report containing context.
// Output -> ~/ghidra_proj/finddefault.txt
import java.io.PrintWriter;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.*;
import ghidra.program.model.mem.*;
public class FindDefault extends GhidraScript {
@Override public void run() throws Exception {
PrintWriter out = new PrintWriter("/home/ntr/ghidra_proj/finddefault.txt");
Memory mem = currentProgram.getMemory();
byte[] pat = { (byte)0x68,(byte)0x4a,(byte)0xf7,(byte)0x78 }; // 0x78f74a68 LE
Address a = mem.getMinAddress();
int found=0;
while (a != null && found < 50) {
Address hit = mem.findBytes(a, pat, null, true, monitor);
if (hit == null) break;
out.println("// 0x78f74a68 bytes @ " + hit);
found++;
a = hit.add(1);
}
out.println("// total occurrences of 0x78f74a68 LE in memory image: " + found);
out.flush(); out.close();
println("wrote finddefault.txt found="+found);
}
}
+51
View File
@@ -0,0 +1,51 @@
// Find the DeviceSQL row-index code that computes index_shift = slot << 5.
// Heuristic: functions that contain BOTH a left-shift-by-5 (SHL r,5 / LEA r,[r*0x20])
// AND reference the row-index masks (0x1fff / 0x7ff) or stride 0x24, AND a u2 store.
// Output -> ~/ghidra_proj/findshift.txt
import java.io.PrintWriter;
import java.util.*;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.program.model.scalar.Scalar;
public class FindShift extends GhidraScript {
@Override public void run() throws Exception {
PrintWriter out = new PrintWriter("/home/ntr/ghidra_proj/findshift.txt");
FunctionManager fm = currentProgram.getFunctionManager();
Listing lst = currentProgram.getListing();
// accumulate per-function evidence
Map<String,Set<String>> ev = new HashMap<>();
InstructionIterator it = lst.getInstructions(true);
while (it.hasNext() && !monitor.isCancelled()) {
Instruction ins = it.next();
Function f = fm.getFunctionContaining(ins.getAddress());
if (f == null) continue;
String key = f.getEntryPoint().toString();
String mn = ins.getMnemonicString();
String txt = ins.toString();
boolean shl5 = (mn.equalsIgnoreCase("SHL") && txt.endsWith(",0x5"))
|| (mn.equalsIgnoreCase("LEA") && txt.contains("*0x20"));
if (shl5) ev.computeIfAbsent(key,k->new HashSet<>()).add("shl5@"+ins.getAddress());
for (int op=0; op<ins.getNumOperands(); op++)
for (Object o : ins.getOpObjects(op))
if (o instanceof Scalar) {
long v = ((Scalar)o).getUnsignedValue();
if (v==0x1fff) ev.computeIfAbsent(key,k->new HashSet<>()).add("mask1fff@"+ins.getAddress());
if (v==0x7ff) ev.computeIfAbsent(key,k->new HashSet<>()).add("mask7ff@"+ins.getAddress());
if (v==0x24) ev.computeIfAbsent(key,k->new HashSet<>()).add("stride24@"+ins.getAddress());
}
}
// report functions that have shl5 AND (mask or stride)
for (Map.Entry<String,Set<String>> e : ev.entrySet()) {
Set<String> tags = e.getValue();
boolean hasShl = tags.stream().anyMatch(t->t.startsWith("shl5"));
boolean hasCtx = tags.stream().anyMatch(t->t.startsWith("mask1fff")||t.startsWith("mask7ff")||t.startsWith("stride24"));
if (hasShl && hasCtx) {
Function f = fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(e.getKey()));
out.println("CANDIDATE " + (f!=null?f.getName():"?") + " @" + e.getKey() + " : " + tags);
}
}
out.flush(); out.close();
println("wrote findshift.txt");
}
}