aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/guard_sweep.py
diff options
context:
space:
mode:
authorPeter Geissler <peter@haxx.in>2026-09-22 11:14:57 +0200
committerPeter Geissler <peter@haxx.in>2026-09-22 11:14:57 +0200
commit649992b26c75eb13ace40c6eec499895a69a1132 (patch)
tree09bfb3ac77a3cc3462d9e2972a678da246cefeb4 /psp_out/guard_sweep.py
downloadamd-psp-re-649992b26c75eb13ace40c6eec499895a69a1132.tar.gz
amd-psp-re-649992b26c75eb13ace40c6eec499895a69a1132.tar.xz
amd-psp-re-649992b26c75eb13ace40c6eec499895a69a1132.zip
Initial import: AMD PSP reverse engineering, emulator and vulnerability research
Split out of a tinygrad working tree, where all of this lived untracked. tinygrad remains a dependency for hardware-facing scripts only. Contents: psp_emu/ Unicorn-based PSP emulator that boots the real signed firmware from the ARM reset vector: sOS -> SYS_DRV -> HDCP/DTM/RAS TAs, with a CCP crypto device model faithful enough to run the firmware's own drivers (RSA-PSS/SHA-256 container verification passes 5/5 with 5/5 negatives rejected). A simulated host drives the real mailbox/ring path through to TA_InvokeCommandEntryPoint. psp_out/ Static analysis: six PSP modules fully named (asd 1562, sys_drv 1141, sos 527, ras 119, hdcp 109, dtm 14) plus SMU 1033, a cross-version diffing pipeline over 34+ builds, per-handler annotated analysis and ~125 findings documents. Deliberately not tracked: AMD firmware images, the Hex-Rays decompilation derived from them, and IDA databases. data/MANIFEST.sha256 pins the SHA-256 of all 301 blobs results were derived from, so findings remain traceable to their inputs without redistributing AMD code. 6 MB tracked instead of 315 MB. Verified from the new location: test_smoke 5/5, ccp_selftest 11/11, verify_real_image 5/5 + 5/5 negatives, fuzz_ta_invoke controls passing and host-driven TA invoke working (0.73s per invoke).
Diffstat (limited to 'psp_out/guard_sweep.py')
-rw-r--r--psp_out/guard_sweep.py50
1 files changed, 50 insertions, 0 deletions
diff --git a/psp_out/guard_sweep.py b/psp_out/guard_sweep.py
new file mode 100644
index 0000000..4148782
--- /dev/null
+++ b/psp_out/guard_sweep.py
@@ -0,0 +1,50 @@
+"""Full corrected added-guard sweep across every module's version chain.
+
+High-signal filter: only COMPARISON instructions (cmp/cmn/tst), and only
+constants that go 0 -> N (newly introduced), which is the strongest evidence of
+an added check. Alignment-aware decode (linear sweep misaligns Thumb).
+
+Validated against ground truth: must rediscover the sOS CCP guard
+(cmp #0xcb00000, 0 -> 1, at .51 -> .52).
+"""
+from capstone import *
+import glob,os,collections,sys
+md=Cs(CS_ARCH_ARM,CS_MODE_THUMB)
+CMPS={'cmp','cmp.w','cmn','cmn.w','tst','tst.w'}
+def census(path):
+ d=open(path,'rb').read()
+ c=collections.Counter()
+ for off in range(0,len(d)-4,2):
+ ins=list(md.disasm(d[off:off+4],off))
+ if not ins: continue
+ i=ins[0]
+ if i.mnemonic not in CMPS or '#' not in i.op_str: continue
+ try: v=int(i.op_str.rsplit('#',1)[1],0)
+ except Exception: continue
+ if v<0x40: continue # skip small loop/flag constants
+ c[v]+=1
+ return c
+def chain_report(name, ordered):
+ print("="*84); print("%s (%d builds)"%(name,len(ordered))); print("="*84)
+ prev=None; prevlbl=None
+ for lbl,p in ordered:
+ cur=census(p)
+ if prev is not None:
+ new=[(v,cur[v]) for v in cur if prev.get(v,0)==0 and cur[v]>0]
+ new.sort(key=lambda t:-t[0])
+ if new:
+ print(" %s -> %s : %d newly-introduced comparison constant(s)"%(prevlbl,lbl,len(new)))
+ for v,n in new[:10]:
+ star=" <<<" if v>=0x10000 else ""
+ print(" cmp #%-12s x%d%s"%(hex(v),n,star))
+ else:
+ print(" %s -> %s : none"%(prevlbl,lbl))
+ prev=cur; prevlbl=lbl
+ print()
+# sOS chain (includes the newly recovered .52)
+sos=[('.37','versions/sos_0.49.0.37_b4f5f2ea.bin'),('.41','versions/sos_0.49.0.41_6504d3cc.bin'),
+ ('.47','versions/sos_0.49.0.47_3be1d3af.bin'),('.48','versions/sos_0.49.0.48_d725e285.bin'),
+ ('.49','versions/sos_0.49.0.49_fc2d5fa0.bin'),('.50','versions/sos_0.49.0.50_e4bc4b17.bin'),
+ ('.51','versions/sos_0.49.0.51_14039a1f.bin'),
+ ('.52*','versions_lfw/sos_3fd1d56b0467c5ea_98944.bin'),('.54','versions/sos_0.49.0.54_3dcb63e8.bin')]
+chain_report("sOS", sos)