aboutsummaryrefslogtreecommitdiffstats
path: root/psp_emu/harness/probe_sysdrv_100b_nested_span.py
diff options
context:
space:
mode:
authoruser <user@clank>2026-10-09 16:11:31 +0200
committeruser <user@clank>2026-10-09 16:11:31 +0200
commitbc43149d914325e15dc0490dee9d982e21287623 (patch)
treea632cf70de742d5a60d01c9c0d806bf5b9257538 /psp_emu/harness/probe_sysdrv_100b_nested_span.py
parentGCP->ASD 0x403: ASD-internal chain PROVEN end-to-end in emulator (real handlers) (diff)
downloadamd-psp-re-main.tar.gz
amd-psp-re-main.tar.xz
amd-psp-re-main.zip
Record PSP security investigation artifacts and probesHEADmain
Diffstat (limited to 'psp_emu/harness/probe_sysdrv_100b_nested_span.py')
-rw-r--r--psp_emu/harness/probe_sysdrv_100b_nested_span.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/psp_emu/harness/probe_sysdrv_100b_nested_span.py b/psp_emu/harness/probe_sysdrv_100b_nested_span.py
new file mode 100644
index 0000000..97b52f2
--- /dev/null
+++ b/psp_emu/harness/probe_sysdrv_100b_nested_span.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+"""Signed .54 0x100B reads nested +16/+20/+24 past four-byte declaration.
+Artificial scratch-page boundary and sOS window; no hardware effect.
+"""
+from pathlib import Path
+import sys
+from unicorn import UC_HOOK_CODE
+from unicorn.arm_const import UC_ARM_REG_R0,UC_ARM_REG_R1,UC_ARM_REG_R2
+sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
+from pspemu import sysdrv_env
+from pspemu.component import Fault
+SIGNED=Path(__file__).resolve().parents[2]/'psp_out/elf/sys_drv_0.49.0.54_18bd9d26.elf'
+
+def main():
+ sd=sysdrv_env.make()
+ assert Path(sd.image_path).read_bytes()==SIGNED.read_bytes()
+ r,f,_=sysdrv_env.run_init(sd)
+ assert r==0 and not f and sysdrv_env.init_flag(sd)==1
+ req,cfg,nested,dummy=[sd.alloc(n) for n in (0x100,0x400,0x40,0x40)]
+ sd.write(cfg,bytes(0x400));sd.write(nested,bytes(0x40));sd.write(dummy,bytes(0x40))
+ sd.wr32(nested+16,0x12340000);sd.wr32(nested+20,1);sd.wr32(nested+24,0x1000)
+ seen=[];allocator=[]
+ sd.uc.hook_add(UC_HOOK_CODE,lambda uc,ea,size,data:seen.append(tuple(uc.reg_read(x) for x in (UC_ARM_REG_R0,UC_ARM_REG_R1,UC_ARM_REG_R2))),begin=0xE086FC,end=0xE086FD)
+ sd.uc.hook_add(UC_HOOK_CODE,lambda uc,ea,size,data:allocator.append(ea),begin=0xE1BBAE,end=0xE1BBAF)
+ def run(ptr,declared):
+ sd.write(req,bytes(0x100))
+ for i,v in ((0,0x100B),(1,2),(2,ptr),(3,declared),(4,dummy),(5,4),
+ (sysdrv_env.REQ_CONFIG_DWORD,cfg)):
+ sd.wr32(req+4*i,v)
+ try:return sd.run_function(0xE087E4,(req,2,0,0),count=2_000_000,timeout=2_000_000)
+ except Fault as exc:return exc
+ mapped=run(nested,4)
+ assert seen and seen[-1]==(1,0x12340000,0x1000),(mapped,seen[-1] if seen else None)
+ # The next page after scratch is deliberately UNMAPPED in this model.
+ edge=sd.cmap.scratch+sd.cmap.scratch_size-4
+ sd.write(edge,b'ABCD')
+ def svc_window(comp,n):
+ p=comp.uc.reg_read(UC_ARM_REG_R1)
+ for i,v in enumerate((sd.cmap.scratch,sd.cmap.scratch+sd.cmap.scratch_size,0,0)):
+ comp.wr32(p+4*i,v)
+ return 0
+ sd.svc.register(0xB5,svc_window)
+ before=len(seen)
+ fault=run(edge,4)
+ assert isinstance(fault,Fault) and fault.addr==edge+24 and fault.pc==0xE1BB80,(fault,seen)
+ assert len(seen)==before
+ denied=run(edge,28)
+ assert not isinstance(denied,Fault) and denied==0xFFFF000F and len(seen)==before,(denied,seen)
+ assert not allocator,allocator
+ print(f'signed 0x100B: nested +16/+20/+24 read after declared4; synthetic edge fault={fault.addr:#x}, declared28 denied={denied:#x}; no mapped hardware claim')
+if __name__=='__main__':main()