# re/ — rekordbox `export.pdb` reverse-engineering Shared record of the Ghidra/Frida work behind maple's pdb writer. See the top-level `README.md` for the high-level findings; this dir holds the raw artifacts so others can reproduce and extend the analysis. ## What's here `scripts/` — Ghidra headless scripts (run against an analyzed `rekordbox.exe`): - `FindPdb.java` — locate the writer via string + magic-constant xrefs - `DecPdb.java` — decompile an explicit list of addresses - `CallTree.java` — walk a call tree, flag file-I/O / 4096-using functions - `FindHash.java` — hunt the per-track hash: decompile `formatForSearch` + callers + content-string xrefs `findings/` — script output (decompiled C + xref maps): - `findpdb.txt` — string xrefs → the export functions; magic-constant hit counts - `decpdb.txt` — decompiled `export.pdb` serializer call stack (DeviceSQL Page Manager) - `calltree.txt` — call tree under the export orchestrator `FUN_14119d2d0` - `hash.txt` — `formatForSearch` + callers + `djmdContent`/`ContentID` xrefs ## Reproduce (not committed: the binary + Ghidra project) `rekordbox.exe` and the analyzed Ghidra project are **not** in the repo (copyright + size). To rebuild from your own rekordbox install (Windows path visible from WSL): ```bash export JAVA_HOME=~/jdk/jdk-21.0.11+10 # Ghidra needs JDK 21 GH=/path/to/ghidra_12.1.2_PUBLIC # one-time: import + analyze (~1h, 10G heap, 8 cores) GHIDRA_HEADLESS_MAXMEM=10G "$GH/support/analyzeHeadless" ~/ghidra_proj rbx \ -import "/mnt/c/Program Files/rekordbox/rekordbox 7.0.5/rekordbox.exe" \ -overwrite -max-cpu 8 -analysisTimeoutPerFile 7200 # then run any script without re-analyzing: "$GH/support/analyzeHeadless" ~/ghidra_proj rbx -process rekordbox.exe -noanalysis \ -scriptPath re/scripts -postScript FindPdb.java ``` Runtime→Ghidra address map: `static = 0x140000000 + module_offset` (Ghidra image base `0x140000000`; ASLR runtime base varies — read `rekordbox.exe+0xOFFSET` from the Frida agent, never hardcode it). ## Live capture (Frida, Windows) `../tools/capture.mjs` (Node, `npm i frida`) + `../tools/rbx_pdb_capture.js` (agent). Child-gates so the CIG-protected writer is hooked at spawn: `node tools/capture.mjs --spawn`. ## Open questions - per-track `0x14` (28-bit) — varies per track, not a plain crc32; likely a stored `djmdContent` value. `0x18`/`0x1a` are a per-export constant. - `index_shift` (row `0x02`) — positional (`~0x20`/row, resets per page) but the exact formula isn't pinned. maple writes `0`; rekordbox doesn't.