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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#!/usr/bin/env python3
"""Run the REAL rom_parse_directory in the emulator, and differential it against
psp_out/ifwi_parse_model.py.
Why this is in scope: no hardware, no flash, no card. CONSTRAINTS.md bars issuing
flash commands to the card; this executes firmware under Unicorn.
Why it matters: ifwi_parse_model.py is a host-side reimplementation of the
pre-auth IFWI parser written to validate crafted images, and it has never been
checked against the firmware it models. The TSU disclosure chain (ANALYSIS-PSP-
CODE-EXEC-AVENUES.md 4.1b/4.1c) rests on that parser's wrapping bounds checks,
so the model has to be right before any crafted input means anything.
Address note: the v53 symbol map's TSU addresses do NOT match this image -- they
have zero callers, while the ANALYSIS/ifwi_parse_model set has 2/1/2/1. This
uses the latter, which is the set that matches the code.
rom_parse_directory(ctx, img) -> err @ 0xE16964
"""
import struct, sys
sys.path.insert(0, "/home/user/dev/amd-psp-re/psp_emu")
sys.path.insert(0, "/home/user/dev/amd-psp-re/psp_out")
from pspemu import sysdrv_env
import importlib.util
_s = importlib.util.spec_from_file_location(
"ifwi", "/home/user/dev/amd-psp-re/psp_out/ifwi_parse_model.py")
IFWI = importlib.util.module_from_spec(_s); _s.loader.exec_module(IFWI)
RPD = 0xE16964
FLASH = "/home/user/dev/amd-psp-re/psp_out/flash_BIOS2_KNOWNGOOD_20260917.bin"
sd = sysdrv_env.make()
sysdrv_env.run_init(sd)
img = open(FLASH, "rb").read()
print("known-good flash image: %d bytes" % len(img))
# place the image somewhere the guest can read
IMG_VA = 0x10000000
sd.uc.mem_map(IMG_VA, (len(img) + 0xFFF) & ~0xFFF)
sd.uc.mem_write(IMG_VA, img)
assert bytes(sd.uc.mem_read(IMG_VA, 4)) == img[:4], "image not readable at IMG_VA"
print("image mapped at %#x, first4 = %s" % (IMG_VA, img[:4].hex()))
ctx = sd.alloc(0x400)
def firmware_parse(image_bytes):
"""Run the real parser over image_bytes; return its error code."""
sd.uc.mem_write(IMG_VA, image_bytes.ljust(len(img), b"\x00")[:len(img)])
sd.write(ctx, b"\x00" * 0x400)
try:
return sd.run_function(RPD, (ctx, IMG_VA, 0, 0), count=20_000_000)
except Exception as e:
return "FAULT:%s" % type(e).__name__
def model_parse(image_bytes):
try:
IFWI.parse(image_bytes)
return 0
except IFWI.Fail as e:
return "Fail:%s" % str(e)[:44]
print("\n=== CONTROL: known-good image ===")
fw = firmware_parse(img)
md = model_parse(img)
print(" firmware rom_parse_directory -> %s" % (hex(fw) if isinstance(fw, int) else fw))
print(" ifwi_parse_model -> %s" % md)
print(" both accept: %s" % (fw == 0 and md == 0))
if fw != 0:
print("\n Firmware rejects the known-good image: either the entry point or the")
print(" calling convention is wrong. Nothing below would mean anything.")
print(" RESULT NOT REPORTABLE")
raise SystemExit(2)
print("\n=== negative control: corrupted magic ===")
bad = bytearray(img); bad[0:4] = b"\xde\xad\xbe\xef"
print(" firmware -> %s" % (lambda v: hex(v) if isinstance(v, int) else v)(firmware_parse(bytes(bad))))
print(" model -> %s" % model_parse(bytes(bad)))
print("\n=== wrapping inputs (the 4.1b claim) ===")
for name, off, val in (("fw_tail slot0 ptr = -0x10", 20, (-0x10) & 0xFFFFFFFF),
("fw_tail slot0 ptr = 0xFFFFFFF0", 20, 0xFFFFFFF0),
("fw_tail slot0 ptr = 0x1FFFF0", 20, 0x1FFFF0)):
t = bytearray(img)
struct.pack_into("<I", t, off, val)
f = firmware_parse(bytes(t)); m = model_parse(bytes(t))
print(" %-30s firmware=%-14s model=%s"
% (name, hex(f) if isinstance(f, int) else f, m))
|