#!/usr/bin/env python3 """ Cinebreak kernel-offsets - locate the 5 offsets Poopsploit needs in a PS5 kernel dump, so new firmwares don't break the chain. Targets (from PS4_KernelOffset.java): prison0 - first struct prison (root jail) [xref: allproc chain walk] rootvnode - vnode pointer of the root filesystem sysent661 - syscall 661 entry in the sysent table jmpRsi - "jmp rsi" gadget in kernel text klLock - kernel lock structure Usage: kernel-offsets.py scan [--base 0xffffffff80000000] kernel-offsets.py selftest """ import sys, struct def scan_gadget(data, pattern, base): """Find all occurrences of a byte pattern; return (offset, vaddr) pairs.""" hits, i = [], 0 while True: i = data.find(pattern, i) if i < 0: break hits.append((i, base + i)) i += 1 return hits def scan_sysent(data, base, n=661, entry_size=0x10): """Locate the sysent table by scanning for a plausible entry 661. Heuristic: 661*entry_size into a table where consecutive entries point into kernel text with monotonically increasing vaddrs.""" text_start, text_end = base + 0x1000, base + len(data) stride = entry_size * n # candidate table starts where entry[n] points into text AND # entries n-2..n+2 are also text pointers (dense syscall table) for i in range(0, len(data) - stride, 0x1000): # 4k-aligned tables ok = True for k in range(n - 2, n + 3): ptr = struct.unpack_from(" "prison_0\0" at 0x600000 struct.pack_into(" {v}") if __name__ == "__main__": if len(sys.argv) > 1 and sys.argv[1] == "selftest": selftest() elif len(sys.argv) >= 3 and sys.argv[1] == "scan": data = open(sys.argv[2], "rb").read() base = int(sys.argv[4], 0) if len(sys.argv) > 4 and sys.argv[3] == "--base" else 0xFFFF000000000000 for k, v in scan(data, base).items(): print(f"{k:12s} -> {v}") else: print(__doc__)