diff options
| author | user <user@clank> | 2026-10-09 16:11:31 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-10-09 16:11:31 +0200 |
| commit | bc43149d914325e15dc0490dee9d982e21287623 (patch) | |
| tree | a632cf70de742d5a60d01c9c0d806bf5b9257538 /psp_emu/harness/probe_sysdrv_53_log_prevalidate.py | |
| parent | GCP->ASD 0x403: ASD-internal chain PROVEN end-to-end in emulator (real handlers) (diff) | |
| download | amd-psp-re-main.tar.gz amd-psp-re-main.tar.xz amd-psp-re-main.zip | |
Diffstat (limited to 'psp_emu/harness/probe_sysdrv_53_log_prevalidate.py')
| -rw-r--r-- | psp_emu/harness/probe_sysdrv_53_log_prevalidate.py | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/psp_emu/harness/probe_sysdrv_53_log_prevalidate.py b/psp_emu/harness/probe_sysdrv_53_log_prevalidate.py new file mode 100644 index 0000000..4f0f03c --- /dev/null +++ b/psp_emu/harness/probe_sysdrv_53_log_prevalidate.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Scope signed .54 low opcode 0x53 logging before caller-string validation. + +Synthetic SVC/PCB/caller window only. No card request or cross-process claim. +Signed SYS_DRV init/dispatch/logging string copy run; MMIO/log-drain effects +are not hardware evidence. +""" +from __future__ import annotations + +import sys +from pathlib import Path +from unicorn import UC_HOOK_CODE, UC_PROT_NONE +from unicorn.arm_const import UC_ARM_REG_R1 + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from pspemu import sysdrv_env # noqa: E402 +from pspemu.component import Fault # noqa: E402 + +SIGNED = Path(__file__).resolve().parents[2] / 'psp_out/elf/sys_drv_0.49.0.54_18bd9d26.elf' +ENTRY = 0xE087E4 +BASE, END = 0x400000, 0x800000 +LOG_FLAG, LOG_LEVEL, BACKEND_FLAG = 0xE264E0, 0xE264E4, 0xE269CC +STRING_HELPER, FORMATTER, DRAIN = 0xE2232C, 0xE01A34, 0xE21D44 +LOG_BUFFER = 0xEB5FB0 + + +def main() -> None: + sd = sysdrv_env.make() + assert Path(sd.image_path).read_bytes() == SIGNED.read_bytes() + rv, fault, _ = sysdrv_env.run_init(sd) + assert rv == 0 and fault is None and sysdrv_env.init_flag(sd) == 1, (rv, fault) + flags = (sd.read(LOG_FLAG, 1)[0], sd.rd32(LOG_LEVEL), sd.read(BACKEND_FLAG, 1)[0]) + print('signed init logging (frontend, level, backend)=', flags, flush=True) + assert flags[0] == 1 and flags[2] == 1, 'both modeled init log gates required' + sd.uc.mem_map(BASE, 0x3000) + regs = sd.uc.mem_regions() + if not any(lo <= END-4 <= hi for lo, hi, _ in regs): + sd.uc.mem_map(END-0x1000, 0x1000) + if any(lo <= END <= hi for lo, hi, _ in sd.uc.mem_regions()): + sd.uc.mem_protect(END, 0x1000, UC_PROT_NONE) + + def svc_window(comp, n): + out = comp.uc.reg_read(UC_ARM_REG_R1) + for i, v in enumerate((BASE, END, 0, 0)): + comp.wr32(out + 4*i, v) + return 0 + sd.svc.register(0xB5, svc_window) + req, cfg = sd.alloc(0x100), sd.alloc(0x400) + sd.write(cfg, b'\x00' * 0x400) + src, edge = BASE+0x1000, END-4 + sd.write(src, b'J' * 40) + sd.write(edge, b'K' * 4) + seen, fmt, before_drain = [], [], [] + sd.uc.hook_add(UC_HOOK_CODE, lambda uc, ea, size, data: seen.append(ea), + begin=STRING_HELPER, end=STRING_HELPER+1) + sd.uc.hook_add(UC_HOOK_CODE, lambda uc, ea, size, data: fmt.append(ea), + begin=FORMATTER, end=FORMATTER+1) + sd.uc.hook_add(UC_HOOK_CODE, + lambda uc, ea, size, data: before_drain.append(bytes( + uc.mem_read(LOG_BUFFER+16, 39))), + begin=DRAIN, end=DRAIN+1) + + def request(ptr: int, declared: int) -> int: + sd.write(req, b'\x00' * 0x100) + for i, word in ((0, 0x53), (2, ptr), (3, declared), (14, 16), + (sysdrv_env.REQ_CONFIG_DWORD, cfg)): + sd.wr32(req + i*4, word) + return sd.run_function(ENTRY, (req, 2, 0, 0), count=3_000_000, + timeout=4_000_000) + + r = request(src, 4) + assert r == 0 and len(seen) == len(fmt) == 1 + assert before_drain == [b'J' * 39], before_drain + print('mapped non-NUL input: declared4, signed logger copied 39 bytes ' + 'before later NUL check; return', hex(r), flush=True) + + n, m, d = len(seen), len(fmt), len(before_drain) + denied = request(edge, 40) + assert denied == 0xFFFF000F and (len(seen),len(fmt),len(before_drain)) == (n,m,d) + print('synthetic edge declared40 rejected before logger',hex(denied),flush=True) + try: + request(edge, 4) + except Fault as exc: + assert exc.addr == END, (exc, sd.faults) + assert (len(seen),len(fmt),len(before_drain)) == (n+1,m+1,d) + print('synthetic edge declared4: signed logger fault at',hex(exc.addr), + 'before later NUL check and log drain',flush=True) + else: + raise AssertionError('short-declared synthetic edge unexpectedly completed') + + +if __name__ == '__main__': + main() |
