1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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()
|