The instruments behind Execution Is Not Extraction →
— the tools built to reverse and emulate the PlayStation 3's Cell/SPU secure-boot chain
(metldr → isoldr → isolated modules) entirely offline, so a hypothesis could be settled on a
workstation instead of on a console that reboots into a red screen of death on every wrong guess.
None of this is a jailbreak or a key dump. It is the measurement rig: emulate the SPU, decompile
it soundly, run the lv1 hypervisor offline, and diff every result against a second implementation so
a decode bug shows up as a divergence instead of a silent wrong answer.
The findings these instruments produced live in a separate record, and each one declares what the tool must still do — exact PCs, exact stop codes, exact hijack counts:
E-0071-boundary-clean svtest 4.20 0xE0 pc == 0x00001b70 and stop == 0x010a
E-0071-boundary-hijack svtest 4.20 0xE4 pc == 0x0003bee0
E-0436-positive-control isofuzz 4.20 hijacks == 11 and coverage >= 598
E-0436-negative isofuzz 4.93 hijacks == 0 and coverage >= 636
E-0129-real-gate verifygate 0xE9 verify == "skipped"
tests/replay_expectations.py replays them, and CI runs it on every pull
request. So an improvement is judged by whether it preserved the record, not by
whether the diff reads well — which is what makes patches to a measurement rig
safe to accept at all.
python3 tests/replay_expectations.py --tool anergistic
Expectations needing firmware or keys skip on public CI, loudly and counted: a run that checked nothing must not look like a run that checked everything. See AGENTS.md.
A fork of fail0verflow's anergistic SPU emulator, extended for isolated-module work:
- an MFC DMA model (single + list transfers, tag groups) so an isolated module's own I/O actually runs;
- taint tracking — follow attacker-controlled bytes into saved registers / the link register;
- channel capture — the outbound mailbox (ch28) and the SPU debug-char console are recorded, not dropped;
- metadata injection past the SRVK barrier, to drive the loader handshakes.
Upstream is GPLv2 and this fork keeps it; original copyright fail0verflow <master@fail0verflow.com>.
Generates a 128-bit lane-correct Ghidra SLEIGH model of the SPU ISA (make_spec.py) plus a
differential harness (vdiff*.py, xport.py, xmatch.py) that diffs every decompiled function
against the anergistic emulator. The two implementations gate each other. Built on top of the
GhidraSPU processor module as its base.
Runs lv1's isolate-load handler chain under Unicorn with catch-and-mock on a 970FX (Cell PPE lineage)
core — no console, no reboot loop. This is what replaced push → launch → RSOD → repeat.
staticlive.py answers the question that kept invalidating offline runs: what does the running
hypervisor hold that the ELF does not? An emulator that demand-maps unseeded memory as zero pages
is green exactly where the hardware machine-checks — so a chain can "complete offline" while
walking pointers that do not exist. This diffs the static image against a live read, follows every
plausible pointer (not only ones whose own value already differs — the divergence is usually one hop
deeper), and recovers r2-relative globals straight from the disassembly, which has full coverage
where tracing a shimmed run does not. On our target 8 of 19 globals on the path under study were
null in the ELF and populated at boot; six of those had been silently read as zero in every offline
run we had trusted. Needs two console-side helpers you supply yourself (see the file header).
Boots a real isoldr under the extended anergistic, clears its loader-channel version handshake
(the gate that stops most attempts), and drives the isolated-module argument staging — all offline.
spu_frame_audit.py sweeps a corpus of decrypted SPU modules for the sv_iso bug class: a
variable-length copy into a stack frame smaller than the copy can be.
lv1 ELF/segment parsing, SPU CFG + callgraph, SS symbol mapping, SCE metadata readout, stack-copy
scanning, string naming.
notedb.py indexes an append-only research log and makes supersession queryable. Long RE
projects retract themselves constantly — a note written on Tuesday overturns Monday's — and flat
files cannot express that, so the older conclusion keeps getting quoted as current. This builds a
SQLite index over notes/NNN-*.md carrying per-note status (closed / retracted / negative) and a
supersession graph, joined on hex addresses because vocabulary drifts and 0x2b80a8 does not.
verdict <term> separates live findings from overturned ones; stale lists every note a later note
killed. Written after a session spent re-deriving results the log already held, because keyword
search returned every note except the ones that had closed the question — they discussed it in
different words.
Tooling only. This repo contains no console keys, no decrypted Sony firmware, and no live console exploit payload — those stay private. The companion writeup is about a defense that holds, not a recipe. Bring your own, legally obtained, firmware to point these tools at.
fail0verflow (anergistic, and the 2010 metldr / ECDSA work), aerosoul94 (GhidraSPU), Mathieulh, geohot, and the wider PS3 scene.
GPLv2, inherited from anergistic. See LICENSE. Third-party components remain under their
own terms.